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