1、代碼python
操做碼 | 功能 |
---|---|
1 | 讀請求,即下載 |
2 | 寫請求,即上傳 |
3 | 表示數據包,即DATA |
4 | 確認碼,即ACK |
5 | 錯誤 |
from socket import * import struct s=socket(AF_INET,SOCK_DGRAM) #建立一個udp的套接字 data=struct.pack("!H5sb5sb",1,b"1.png",0,b"octet",0) #按照TFTP數據包的格式,構造讀寫請求。"!"表示網絡傳輸;H表示2個字節;s表示字符類;b表示 byte類型;數字表示重複幾回。 #octet表示八進制,此處固定寫法。 # b"字符串" 轉化爲byte s.sendto(data,("192.168.249.55",69)) #將構造的TFTP數據包發送到TFTP服務器上69端口。 fp=open("/home/python/tupian1.png","wb") #在本機上打開並創建一個新文件 while(True): data=s.recvfrom(1024) print("從ip號%s,端口號%d的主機接受到數據:"%(data[1][0],data[1][1])) #接收來的data爲一個元組,data=(data[0],(data[1][0],data[1][1])),data[0]表示516個字節的數據報,後面的是服務器發送數據報的ip地址和端口號。 #接收的TFTP數據報大小爲516個字節,其中前2個字節表示操做碼,日後2個字節表示數據報序號,後面的512個字節表示數據報數據。 op_bl= struct.unpack("!HH",data[0][:4]) #解包操做,data[0]表示TFTP的516個字節,data[0][:4]表示操做碼和塊編號。 _data=data[0][4:] #data[0][4:] 表示數據包的數據,佔512byte if(op_bl[0]==5): #當操做碼等於5的時候,表示錯誤 print("出差錯,差錯碼是%d,"%op_bl[1]) elif op_bl[0]==3: #當操做碼等於3的時候,表示數據包 data_ack=struct.pack("!HH",4,op_bl[1]) #造成ACK,4表示操做碼,op_bl[1]表示塊編號 fp.write(_data) #將塊數據部分寫入新文檔 if len(data[0]) < 516: #當數據包內容小於516時表示文件已經傳輸完畢 s.sendto(data_ack, ("192.168.249.55", data[1][1])) #將ACK回覆服務器 break else: s.sendto(data_ack, ("192.168.249.55", data[1][1])) else: print("異常") fp.close() #關閉文檔 s.close() #關閉套接字