python编写tftp服务器

曹光霁
2023-12-01
  1. tftp服务起下载文件
    	from socket import *
    	import struct 
    	import os
    	import sys
    	
    	
    	def main():
    	    if len(sys.argv) != 3:
    	        print("请按照规则运行程序:python3 xxx.py ip filename")
    	        exit()
    	
    	    #服务器ip
    	    tftp_ip = sys.argv[1]
    	
    	    #文件名字
    	    file_name = sys.argv[2]
    	
    	    #名字大小
    	    file_num = len(file_name)
    	
    	    #下载请求
    	    cmd_buf = struct.pack("!H%dsb5sb"%file_num,1,file_name.encode("utf-8"),0,"octet".encode("utf-8"),0)
    	
    	    #创建套接字
    	    socket_udp = socket(AF_INET,SOCK_DGRAM)
    	
    	    #给服务器发送我需要的东西
    	    socket_udp.sendto(cmd_buf,(tftp_ip,69))
    	
    	    #打开一个文件
    	    f = open(file_name,"bw")
    	
    	    flag = True
    	
    	    num = 0
    	
    	    while True:
    	        result = socket_udp.recvfrom(1024)
    	        
    	        #数据     新ip端口
    	        tftp_data,tftp_ip_port = result
    	        
    	        #操作号
    	        cmd_tuple = struct.unpack("!H",tftp_data[:2])
    	
    	        #块编号
    	        cmd_tuple2 = struct.unpack("!H",tftp_data[2:4])    
    	
    	        #操作码
    	        tftp_opcode = cmd_tuple[0]
    	
    	        #块编号
    	        tftp_serial_number = cmd_tuple2[0]
    	
    	        #打印当前快编号
    	        print(tftp_serial_number)
    	
    	
    	        if tftp_opcode == 3: #是否为数据
    	
    	             #计算出这次应该接收到的文件的序号值,应该是上一次接收到的值的基础上+1
    	            num = num + 1
    	
    	            # 如果一个下载的文件特别大,即接收到的数据包编号超过了2个字节的大小
    	            # 那么会从0继续开始,所以这里需要判断,如果超过了65535 那么就改为0
    	            if num == 65536: 
    	                num = 0
    	            
    	            if num == tftp_serial_number: # 用块编号测试是否有重复数据
    	                f.write(tftp_data[4:])
    	
    	            #测试Ack
    	            cmd_buf2 = struct.pack("!HH",4,tftp_serial_number)
    	
    	            #把当前接收到的 快编号发送个服务器 随机端口和ip
    	            socket_udp.sendto(cmd_buf2,tftp_ip_port)
    	            
    	            #测试数据长度
    	            if len(tftp_data) < 516:
    	                print("传输完毕.....")
    	                break
    	
    	        elif tftp_opcode == 5:
    	            print("没有这个文件夹......")
    	            flag = Falsh
    	
    	    if flag == True:
    	        f.close() #关闭文件
    	
    	    else:
    	        os.unlink(file_name)#没有这个文件 把创建的文件删除
    	
    	    socket_udp.close() #关闭套接字
    	
    	
    	if __name__ == "__main__":
    	    main()
    
  2. tftp服务器上传文件
    	from socket import *
    	import struct
    	import sys
    	import os
    	
    	
    	#上传的主要核心你要知道你是发送方
    	#服务器是接收方  服务器反回确认信息,或者报错信息
    	def main():
    	    if len(sys.argv) != 3:
    	        print("python3 xxx.py ip filename")
    	        exit()
    	
    	
    	    tftpd_ip = sys.argv[1]
    	    tftpd_file_name = sys.argv[2]
    	
    	    #打包
    	    cmd_buf = struct.pack("!H%dsb5sb"%len(tftpd_file_name),2,tftpd_file_name.encode("utf-8"),0,"octet".encode("utf-8"),0)
    	
    	    socket_udp = socket(AF_INET,SOCK_DGRAM)
    	
    	    socket_udp.sendto(cmd_buf,(tftpd_ip,69))
    	
    	    f = open(tftpd_file_name,"br")
    	
    	    num = 1  #这里写1是因为  我上面发送了一次的
    	
    	    flag = True
    	
    	    while True:
    	        result = socket_udp.recvfrom(1024)
    	
    	        #服务起反回的确认信息 和 ip port
    	        tftpd_data,tftpd_ip_port = result
    	
    	        #操作号 服务的确认的操作好
    	        op_num = struct.unpack("!H",tftpd_data[:2])
    	
    	        #块编号 服务起反回的快编号
    	        pack_num = struct.unpack("!H",tftpd_data[2:4])
    	
    	        print(pack_num[0])
    	
    	        if op_num[0] == 4:
    	            
    	            if num-1 == pack_num[0]:  # 这里写num-1  是因为 pack_num[0] 是反回的我上次发的快编号
    	                send_data = f.read(512)
    	
    	                if len(send_data) < 512:
    	                    print("传输完成........")
    	                    break
    	                                                                #num是快编号 因为我是发送方 我要自做个快比那好
    	                cmd_bug = struct.pack("!HH%ds"%len(send_data),3,num,send_data) #send_data是读取的文件信息
    	                socket_udp.sendto(cmd_bug,tftpd_ip_port) #发给服务器
    	
    	                num = num + 1 #我的快编号加1
    	
    	        elif op_num[0] == 5:
    	            print("没有这个文件......")
    	            flag = Falsh
    	            break
    	            
    	    if flag == True:
    	        f.close()
    	    else:
    	        os.unlink(tftpd_file_name) #删除这个文件
    	
    	if __name__ == "__main__":
    	    main()
    
 类似资料: