python3编写tftp下载器

代码

from socket import *
import struct
import os
def main():
    udp_socket = socket(AF_INET, SOCK_DGRAM)
    bind_addr = ('', 2018)
    ip_portID = ('192.168.0.101', 69)
    udp_socket.bind(bind_addr)
    msg = struct.pack('!H%dsb5sb' % len(download_filename), 1, download_filename.encode(), 0, 'octet'.encode(), 0)
    udp_socket.sendto(msg, ip_portID)
    #udp是面向无连接的所以用sendto和recvfrom里面加(ip,port_id);
    #tcp则是面向有连接的,使用send和recv后面也不用再加(ip,port_id)

    while True:
        recv_info,recv_ip_Port_tuple = udp_socket.recvfrom(1024)

        #检测服务器是不是随机端口发回来的消息,
        #事实证明确实是随机端口,以后发的ack也要往对应的随机端口回而不是69端口
        #print (recv_ip_Port_tuple)

        recv_data = struct.unpack('!HH', recv_info[:4])
         # recv_data是个元祖比如(5,1); 5和1分别占2个Bytes所以 要按 '!HH'格式unpack出来

        #申请的文件服务器中不存在的情况
        if recv_data[0] == 5:

            #打印文件不存在的信息
            print (recv_info[4:].decode())

        #收到的操作码是3并且块编号是1,创建一个文件并将数据保存,并向随机端口回一个ACK (4,块编号)
        elif recv_data[0] == 3:

            # 如果是第一块数据
            if recv_data[1] == 1:
                print (recv_data[1])
                f = open(download_filename,'ab')
                f.write(recv_info[4:])
                
                #判断是不是最后一块数据,不是就回ack
                if len(recv_info) < 516:
                    break
                else:
                    ack = struct.pack('!HH',4,recv_data[1])
                    udp_socket.sendto(ack,recv_ip_Port_tuple)

            # 收到操作码3且块编号不是1继续保存数据
            else:
            	#打印数据块序号可写可不写
                print (recv_data[1])

                f.write(recv_info[4:])
                
			#判断是不是最后一块数据,不是就回ack
                if len(recv_info) < 516:
                    break
                else:
                    ack = struct.pack('!HH', 4, recv_data[1])
                    udp_socket.sendto(ack,recv_ip_Port_tuple)

    f.close()
    udp_socket.close()
if __name__ == '__main__':
    download_filename = input('请输入要下载的文件名(包括后缀):')
    if  download_filename in os.listdir():
        print ('文件已存在或者文件名与当前文件夹中的文件重名!!')
    else:
        main()

猜你喜欢

转载自blog.csdn.net/qq_41992088/article/details/84189104
今日推荐