#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()