Python设计TFTP客户端

#coding=utf-8

from socket import *
from threading import Thread
import struct

def recvData(fileName,udpSocket,lastBlockNum):
    lastBlockNum = lastBlockNum
    cycleIndex = 0 #当文件较大,块编号大于65535时,循环索引加1,重置块编号为1
    while True:
        dataInfo, dstInfo = udpSocket.recvfrom(1024)
        opCode,blockNum = struct.unpack("!HH",dataInfo[:4])
        if opCode == 3:
            if blockNum == 1 and cycleIndex==0:
                f = open(fileName,'wb')
            data_fmt = '!%ds'%(len(dataInfo)-4)
            data_content = struct.unpack(data_fmt,dataInfo[4:])

            if lastBlockNum+1 == blockNum:
                f.write(data_content[0])

            ack_data = struct.pack("!HH",4,blockNum)
            udpSocket.sendto(ack_data,dstInfo)

            if blockNum==65535:
                cycleIndex += 1
                lastBlockNum = blockNumelif blockNum>65535:
                lastBlockNum=0
            else:
                lastBlockNum = blockNum

            if len(dataInfo)<516:
                print("下载完毕!")
                f.close()
                break
        elif opCode == 5:
            errorNum = blockNum
            err_fmt = "!%ds"%(len(dataInfo)-5)
            errorMsg = struct.unpack(err_fmt,dataInfo[4:-1])
            print("出错信息%s %s"%(errorMsg,errorNum))
            break


def sendData(fileName,udpSocket):
    ipInfo = ("10.0.0.4", 69)
    dataInfo = struct.pack("!H%dsB5sB"%len(fileName), 1, fileName.encode("gb2312"), 0, 'octet'.encode("gb2312"), 0)
    udpSocket.sendto(dataInfo, ipInfo)

def main():
    fileName = "CentOS-7-x86_64-Minimal-1611.iso"
    udpSocket = socket(AF_INET, SOCK_DGRAM)
    bind = ("", 38438)
    udpSocket.bind(bind)
    lastBlockNum = 0

    t1 = Thread(target=sendData,args=(fileName,udpSocket,))
    t1.start()

    t2 = Thread(target=recvData,args=(fileName,udpSocket,lastBlockNum))
    t2.start()

if __name__ == "__main__":
    main()
转载请注明出处:http://www.cnblogs.com/sexyboy/
原文地址:https://www.cnblogs.com/sexyboy/p/8509578.html