TFTP协议Pyhton客户端

Zss 发表于:

1.TFTP(Trivial File Transfer Protocol,简单文件传输协议)是TCP/IP协议族中的一个用来在客户机与服务器之间进行简单文件传输的协议,基于UDP实现。提供不复杂、开销不大的文件传输服务。端口号为69

2.协议的格式:

操作码的位置:1客户端代表请求下载   2代表客户端请求上传   3代表数据   4代表客户端发送给服务端的ack确认  5表示错误码

这体现了五种不同的tftp报文

TFTP报文的头两个字节表示操作码,对于读请求和写请求(WRQ),文件名字段说明客户要读或写的位于服务器上的文件。模式字段是一个ASCII码串netascii或octet

3.TFTP的工作过程

   TFTP的工作过程很像停止等待协议,发送完一个文件块后就等待对方的确认,确认时应指明所确认的块号。发送万数据后在规定时间内收不到确认就要重发数据PDU
发送确认PDU的一方弱在规定时间内收不到下一个文件块,也要重发确认PDU。这样保证文件的传送不致因某一个数据报的丢失而告失败

通过wireshark抓取一个下载完整的过程

客户端想服务端发送下载请求  其中包括了下载还是上传什么文件名和什么模式,server端发送给客户端文件大小,客户端确认,之后一系列的下载,没下载一个数据包回应一个ack确认

#conding:utf-8#
from socket import *
import struct

senddata = struct.pack('!H10sb5sb',1,'testpg.jpg',0,'octet',0)
udpsocket = socket(AF_INET,SOCK_DGRAM)
udpsocket.sendto(senddata,('192.168.16.109',69))
f = open('testpg.jpg','w')
num = 0
while 1:
    rspdata = udpsocket.recvfrom(1024)  #接收数据
    data,ip_port = rspdata #将数据包分为数据部分和server的相关ip和端口,为了方便发送ack

    opnumber = struct.unpack('!H',data[:2])
    packnumber = struct.unpack('!H',data[2:4])
    #print(opnumber,packnumber)
    if opnumber[0]==3: #判断操作码是不是3  如果是说明为数据,将数据写入
        f.write(data)
        ackdata = struct.pack('!HH',4,packnumber[0]) 
        udpsocket.sendto(ackdata,ip_port)#写入数据后回复服务器ack确认
        #num +=1
        print(len(data))
        if len(data)<516:#用来确认文件的传输是否完成,用最后一个数据包来判断是否小于中间传输的516字节大小
            break

struct.pack(‘!H10sb5sb’,1,’testpg.jpg’,0,’octet’,0)  用来封装包

struct.unpack(‘!H’,data[2:4])   用来解包

H代表两个字节,10s代表10个字节,b代表一个字节