本帖最后由 我是楠楠 于 2019-11-28 11:17 编辑
【郑州校区】网络协议TFTP TFTP(Trivial File Transfer Protocol,简单文件传输协议)是TCP/IP协议族中的一个用来在客户端与服务器之间进行简单文件传输的协议。和使用TCP的文件传输协议(FTP)不同,为了保持简单短小,TFTP使用了UDP。TFTP的实现(和它所需要的UDP、IP、和设备驱动程序)可以放入只读存储器中 TFTP是一个简单的协议,适合于只读存储器,仅用于无盘系统进行系统引导,它只使用几种报文格式,是一种停止等待协议 特点:
1、简单
2、占用资源小
3、适合传递小文件
4、适合在局域网进行传递
5、端口号为69
6、基于UDP实现 缺陷:
TFTP分组中并不提供用户名和口令。这是TFTP的一个特性(即"安全漏洞")。由于TFTP是设计用于系统引导进程,它不可能提供用户名和口令。
目前大多数TFTP服务器提供了一个选项来限制只能访问特定目录下的文件,这个目录中只包含无盘系统进行系统引导时所需的文件
当服务器找到需要现在的文件后,会立刻打开文件,把文件中的数据通过TFTP协议发送给客户端
如果文件的总大小较大(比如3M),那么服务器分多次发送,每次会从文件中读取512个字节的数据发送过来 因为发送的次数有可能会很多,所以为了让客户端对接收到的数据进行排序,所以在服务器发送那512个字节数据的时候,会多发2个字节的数据,用来存放序号,并且放在512个字节数据的前面,序号是从1开始的 因为需要从服务器上下载文件时,文件可能不存在,那么此时服务器就会发送一个错误的信息过来,为了区分服务发送的是文件内容还是错误的提示信息,所以又用了2个字节 来表示这个数据包的功能(称为操作码),并且在序号的前面。 为了允许多个客户端同时进行系统引导,TFTP服务器必须提供一定形式的并发。因为UDP在一个客户与一个服务器之间并不提供唯一连接,TFTP服务通过对每个客户提供一个新的UDP端口来提供并发。这样允许不同的客户输入数据报,然后由服务器中的UDP模块根据目的端口号进行区分,而不是由服务器本身来进行区分。
因为udp的数据包不安全,即发送方发送是否成功不能确定,所以TFTP协议中规定,为了让服务器知道客户端已经接收到了刚刚发送的那个数据包,所以当客户端接收到一个数据包的时候需要向服务器进行发送确认信息,即发送收到了,这样的包成为ACK(应答包) 为了标记数据已经发送完毕,所以规定,当客户端接收到的数据小于516(2字节操作码+2个字节的序号+512字节数据)时,就意味着服务器发送完毕了 TFTP数据包格式如下: ---------------------代码案例实现--------------------- [AppleScript] 纯文本查看 复制代码 #coding=utf-8
2
3 #进行对应包的引用
4 from socket import *
5
6 import struct
7
8 import sys
9
10 #创建一个套接字进行网络通信
11 soc =socket(AF_INET,SOCK_DGRAM)
12
13 #获取对应传递的ip地址参数
14 strIp=sys.argv[1]
15
16 #元组,放对应的ip地址和端口号
17 addr=(strIp,69)
18
19 #参数:现在文件的名字
20 strName=sys.argv[2]
21
22 #进行组包,提交给TFTP服务
23 sendData=struct.pack("!H"+str(len(strName))+"sb5sb",1,strName,0,"octet",0)
24
25 #数据的发送
26 soc.sendto(sendData,addr)
27
28 #初始化文件管理对象
29 fil=''
30
31 #下载后的文件重命名
32 filName=sys.argv[2]
33
34 while True:
35 #接受服务器的相应数据(内容,(ip,端口))
36 recvData,recvAddr=soc.recvfrom(1024)
37
38 #对接受的数据进行处理
39 opkey=struct.unpack("!HH",recvData[:4])
40
41 print(opkey)
42
43 #变量存储序号
44 pNum=opkey[1]
45
46 #3判断,从服务器上下载的数据
47 if opkey[0]==3:
48 #第一次数据传递时,进行对应的文件的创建
49 if pNum==1:
50 fil=open(filName,"w")
51 #数据的写入
52 fil.write(recvData[4:])
53
54 if len(recvData)<516:
55
56 fil.close()
57 print("下载完成!")
58 break
59
60 #5判断,TFTP服务器出现错误
61 if opkey[0]==5:
62 print("运行错误!")
63 break
64
65 #组包
66 ackData=struct.pack("!HH",4,pNum)
67
68 soc.sendto(ackData,recvAddr)
69 soc.close() ---------------------附件struct表--------------------
|