Python实现TFTP上传和下载

Python实现TFTP上传和下载

1. TFTP协议介绍

  • TFTP(Trivial File Transfer Protocol,简单⽂件传输协议)是TCP/IP协议族中的⼀个⽤来在客户端与服务器之间进⾏简单⽂件传输的协议
  • 特点:
    • 简单
    • 占⽤资源⼩
    • 适合传递⼩⽂件
    • 适合在局域⽹进⾏传递
    • 端⼝号为69
    • 基于UDP实现

2. TFTP客户端服务器交互过程

  • TFTP服务器默认监听69号端⼝,当客户端发送“下载”请求(即读请求)时,需要向服务器的69端⼝发送,服务器若批准此请求,则使⽤⼀个新的、临时的 端⼝进⾏数据传输。
  • TFTP客户端服务器交互过程,图片来自百度图片
  • 图片来自百度图片
  • TFTP数据包格式,图片来自百度图片

TFTP文件上传下载过程分析

1、下载过程

  • 第一步:客户端给服务器发送下载请求,数据格式为(操作码1+文件名+0+模式+0)。
  • 第二步:服务器接收到请求之后,回复客户端消息,数据格式为元组类型。(操作码3+块编码0+数据, (IP号, 端口号))。
  • 第三步:客户端每接受一次数据,都要回复服务器一次ACK信号。
  • 第四步:直到客户端接收到的数据小于516个字节,才说明服务器发送完毕!

2、上传过程

  • 第一步:客户端给服务器发送上传请求,数据格式为(操作码2+文件名+0+模式+0)。
  • 第二步:服务器接收到请求之后,回复客户端ACK消息,数据格式为元组类型。(操作码4+块编码0, (IP号, 端口号))。
  • 第三步:客户端每发送一次数据,服务器都要回复一次ACK信号。

Python实现TFTP客户端上传下载代码


	"""
	tftp下载文件
	地址:("127.0.0.1", 69)
	"""
	import struct
	import socket 
	import sys
	
	
	ip = ""
	filename = ""
	s = None
	
	def handle_argv():
	    """处理输入参数"""
	    global ip
	    global filename
	
	    if len(sys.argv) != 3:
	        print("-"*30)
	        print("请输入正确格式:python xxx.py ip filename")
	        print("例如:python xxx.py 127.0.0.1, test.txt")
	        print("-"*30)
	    else:
	        ip = sys.argv[1]
	        filename = sys.argv[2]
	
	
	def recv_data():
	    """接收数据"""
	    data_length = 0
	    code = 0
	    block_number = 0
	    current_number = 0
	
	    while True:
	        data, addr = s.recvfrom(1024)
	
	        # code_tuple = struct.unpack("!HH", data[:4])
	        # print(code_tuple) # (3, 1)
	        code, current_number = struct.unpack("!HH", data[:4])
	        data_length = len(data)
	
	        if code == 3: 
	            
	            if current_number == 1:
	                f = open(filename, 'ab')
	            
	            if block_number+1 == current_number:
	                f.write(data[4:])
	                block_number += 1
	                print("第{}次接收到数据!".format(current_number))
	
	                reply_info = struct.pack('!HH', 4, block_number)
	                s.sendto(reply_info, addr)
	            
	            if data_length < 516:
	                f.close()
	                print("下载完成!")
	                break
	
	        else:
	            print("error info {}:", data.decode())
	            break  
	
	
	def main():
	    global s
	
	    handle_argv()
	
	    read_args = struct.pack("!H{}sb5sb".format(len(filename)), 1, filename.encode(), 0, 'octet'.encode(), 0)
	    
	    s = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
	    s.bind(("127.0.0.1", 6666))
	    
	    # IP可变, 端口固定
	    # s.sendto(read_args, ("127.0.0.1", 69))
	    s.sendto(read_args, (ip, 69))   
	
	    recv_data()
	
	    s.close()
	
	
	if __name__ == "__main__":
	    main()


	"""
	tftp上传文件
	地址:('127.0.01', 69)
	"""
	
	import socket 
	import struct
	import sys
	
	
	ip = ""
	filename = ""
	s = None
	
	
	def handle_argv():
	    """处理输入参数"""
	    global ip
	    global filename
	
	    if len(sys.argv) != 3:
	        print("-"*30)
	        print("请输入正确格式:python xxx.py ip filename")
	        print("例如:python xxx.py 127.0.0.1, test.txt")
	        print("-"*30)
	    else:
	        ip = sys.argv[1]
	        filename = sys.argv[2]
	
	
	def upload_file():
	    """上传文件"""
	    code = 0
	    block_number = 0
	    current_number = 1
	
	    while True:
	        data, addr = s.recvfrom(1024)
	
	        code, block_number = struct.unpack("!HH", data[:4])
	
	        if code == 4:
	            if block_number == 0:
	                f = open(filename, 'rb')
	
	            if block_number+1 == current_number:
	                file_data = f.read(512)
	                send_data = struct.pack('!HH', 3, current_number) + file_data
	                s.sendto(send_data, addr)
	                print("第{}次传输数据!".format(current_number))
	                
	                block_number += 1
	                current_number += 1
	
	            if len(send_data) < 516:
	                f.close()
	                print("文件上传完成!")
	                break
	
	        elif code == 5:
	            f.close()
	            print("上传文件失败!error info: {}".format(data[4:].decode()))
	            break
	
	
	def main():
	    global s
	
	    handle_argv()
	
	    upload_args = struct.pack("!H{}sb5sb".format(len(filename)), 2, filename.encode(), 0, "octet".encode(), 0)
	
	    s = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
	    s.bind(("127.0.0.1", 6666))
	
	    s.sendto(upload_args, ("127.0.0.1", 69))
	
	    upload_file()
	
	    s.close()
	
	if __name__ == "__main__":
	    main()

  • 2
    点赞
  • 17
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值