1.版本1:发送请求
# -*- coding:utf-8 -*- import struct from socket import * #0. 获取要下载的文件名字: downloadFileName = raw_input("请输入要下载的文件名:") #1.创建socket udpSocket = socket(AF_INET, SOCK_DGRAM) requestFileData = struct.pack("!H%dsb5sb"%len(downloadFileName), 1, downloadFileName, 0, "octet", 0) #2. 发送下载文件的请求 udpSocket.sendto(requestFileData, ("192.168.119.215", 69))
2.版本2:回复ack
# -*- coding:utf-8 -*- import struct from socket import * #0. 获取要下载的文件名字: downloadFileName = raw_input("请输入要下载的文件名:") #1.创建socket udpSocket = socket(AF_INET, SOCK_DGRAM) requestFileData = struct.pack("!H%dsb5sb"%len(downloadFileName), 1, downloadFileName, 0, "octet", 0) #2. 发送下载文件的请求 udpSocket.sendto(requestFileData, ("192.168.119.215", 69)) #3. 接收服务发送回来的应答数据 responseData = udpSocket.recvfrom(1024) # print(responseData) recvData, serverInfo = responseData opNum = struct.unpack("!H", recvData[:2]) packetNum = struct.unpack("!H", recvData[2:4]) print(packetNum[0])
3.版本3:while True 循环
# -*- coding:utf-8 -*- import struct from socket import * import time import os def main(): #0. 获取要下载的文件名字: downloadFileName = raw_input("请输入要下载的文件名:") #1.创建socket udpSocket = socket(AF_INET, SOCK_DGRAM) requestFileData = struct.pack("!H%dsb5sb"%len(downloadFileName), 1, downloadFileName, 0, "octet", 0) #2. 发送下载文件的请求 udpSocket.sendto(requestFileData, ("192.168.119.215", 69)) while True: #3. 接收服务发送回来的应答数据 responseData = udpSocket.recvfrom(1024) # print(responseData) recvData, serverInfo = responseData opNum = struct.unpack("!H", recvData[:2]) packetNum = struct.unpack("!H", recvData[2:4]) print(packetNum[0]) time.sleep(0.1) if __name__ == '__main__': main()
4.版本4:跳出循环
# -*- coding:utf-8 -*- import struct from socket import * import time import os def main(): #0. 获取要下载的文件名字: downloadFileName = raw_input("请输入要下载的文件名:") #1.创建socket udpSocket = socket(AF_INET, SOCK_DGRAM) requestFileData = struct.pack("!H%dsb5sb"%len(downloadFileName), 1, downloadFileName, 0, "octet", 0) #2. 发送下载文件的请求 udpSocket.sendto(requestFileData, ("192.168.119.215", 69)) flag = True #表示能够下载数据,即不擅长,如果是false那么就删除 num = 0 f = open(downloadFileName, "w") while True: #3. 接收服务发送回来的应答数据 responseData = udpSocket.recvfrom(1024) # print(responseData) recvData, serverInfo = responseData opNum = struct.unpack("!H", recvData[:2]) packetNum = struct.unpack("!H", recvData[2:4]) print(packetNum[0]) time.sleep(0.1) if len(recvData)<516: break if __name__ == '__main__': main()
5.版本5:优化版本,文件不存在
# -*- coding:utf-8 -*- import struct from socket import * import time import os def main(): #0. 获取要下载的文件名字: downloadFileName = raw_input("请输入要下载的文件名:") #1.创建socket udpSocket = socket(AF_INET, SOCK_DGRAM) requestFileData = struct.pack("!H%dsb5sb"%len(downloadFileName), 1, downloadFileName, 0, "octet", 0) #2. 发送下载文件的请求 udpSocket.sendto(requestFileData, ("192.168.119.215", 69)) flag = True #表示能够下载数据,即不擅长,如果是false那么就删除 num = 0 f = open(downloadFileName, "w") while True: #3. 接收服务发送回来的应答数据 responseData = udpSocket.recvfrom(1024) # print(responseData) recvData, serverInfo = responseData opNum = struct.unpack("!H", recvData[:2]) packetNum = struct.unpack("!H", recvData[2:4]) print(packetNum[0]) # print("opNum=%d"%opNum) # print(opNum) # if 如果服务器发送过来的是文件的内容的话: if opNum[0] == 3: #因为opNum此时是一个元组(3,),所以需要使用下标来提取某个数据 #计算出这次应该接收到的文件的序号值,应该是上一次接收到的值的基础上+1 num = num + 1 # 如果一个下载的文件特别大,即接收到的数据包编号超过了2个字节的大小 # 那么会从0继续开始,所以这里需要判断,如果超过了65535 那么就改为0 if num==65536: num = 0 # 判断这次接收到的数据的包编号是否是 上一次的包编号的下一个 # 如果是才会写入到文件中,否则不能写入(因为会重复) if num == packetNum[0]: # 把收到的数据写入到文件中 f.write(recvData[4:]) num = packetNum[0] #整理ACK的数据包 ackData = struct.pack("!HH", 4, packetNum[0]) udpSocket.sendto(ackData, serverInfo) elif opNum[0] == 5: print("sorry,没有这个文件....") flag = False # time.sleep(0.1) if len(recvData)<516: break if flag == True: f.close() else: os.unlink(downloadFileName)#如果没有要下载的文件,那么就需要把刚刚创建的文件进行删除 if __name__ == '__main__': main()
6.版本6:第二种参考程序
#coding=utf-8 from socket import * import struct import sys if len(sys.argv) != 2: print('-'*30) print("tips:") print("python xxxx.py 192.168.1.1") print('-'*30) exit() else: ip = sys.argv[1] # 创建udp套接字 udpSocket = socket(AF_INET, SOCK_DGRAM) #构造下载请求数据 cmd_buf = struct.pack("!H8sb5sb",1,"test.jpg",0,"octet",0) #发送下载文件请求数据到指定服务器 sendAddr = (ip, 69) udpSocket.sendto(cmd_buf, sendAddr) p_num = 0 recvFile = '' while True: recvData,recvAddr = udpSocket.recvfrom(1024) recvDataLen = len(recvData) # print recvAddr # for test # print len(recvData) # for test cmdTuple = struct.unpack("!HH", recvData[:4]) # print cmdTuple # for test cmd = cmdTuple[0] currentPackNum = cmdTuple[1] if cmd == 3: #是否为数据包 # 如果是第一次接收到数据,那么就创建文件 if currentPackNum == 1: recvFile = open("test.jpg", "a") # 包编号是否和上次相等 if p_num+1 == currentPackNum: recvFile.write(recvData[4:]); p_num +=1 print '(%d)次接收到的数据'%(p_num) ackBuf = struct.pack("!HH",4,p_num) udpSocket.sendto(ackBuf, recvAddr) # 如果收到的数据小于516则认为出错 if recvDataLen<516: recvFile.close() print '已经成功下载!!!' break elif cmd == 5: #是否为错误应答 print "error num:%d"%currentPackNum break udpSocket.close()