TFTP(Trivial File Transfer Protocol,簡單文件傳輸協議)是TCP/IP協議族中的一個用來在客戶端與服務器之間進行簡單文件傳輸的協議。和使用TCP的文件傳輸協議(FTP)不同,為了保持簡單短小,TFTP使用了UDP。TFTP的實現(和它所需要的UDP、IP、和設備驅動程序)可以放入只讀存儲器中
TFTP是一個簡單的協議,適合於只讀存儲器,僅用於無盤系統進行系統引導,它只使用幾種報文格式,是一種停止等待協議
特點:
1、簡單
2、占用資源小
3、適合傳遞小文件
4、適合在局域網進行傳遞
5、端口號為69
6、基於UDP實現
缺陷:
TFTP分組中並不提供用戶名和口令。這是TFTP的一個特性(即"安全漏洞")。由於TFTP是設計用於系統引導進程,它不可能提供用戶名和口令。
目前大多數TFTP服務器提供了一個選項來限制只能訪問特定目錄下的文件,這個目錄中只包含無盤系統進行系統引導時所需的文件
當服務器找到需要現在的文件后,會立刻打開文件,把文件中的數據通過TFTP協議發送給客戶端
如果文件的總大小較大(比如3M),那么服務器分多次發送,每次會從文件中讀取512個字節的數據發送過來
因為發送的次數有可能會很多,所以為了讓客戶端對接收到的數據進行排序,所以在服務器發送那512個字節數據的時候,會多發2個字節的數據,用來存放序號,並且放在512個字節數據的前面,序號是從1開始的
因為需要從服務器上下載文件時,文件可能不存在,那么此時服務器就會發送一個錯誤的信息過來,為了區分服務發送的是文件內容還是錯誤的提示信息,所以又用了2個字節 來表示這個數據包的功能(稱為操作碼),並且在序號的前面。
為了允許多個客戶端同時進行系統引導,TFTP服務器必須提供一定形式的並發。因為UDP在一個客戶與一個服務器之間並不提供唯一連接,TFTP服務通過對每個客戶提供一個新的UDP端口來提供並發。這樣允許不同的客戶輸入數據報,然后由服務器中的UDP模塊根據目的端口號進行區分,而不是由服務器本身來進行區分。
操作碼 | 功能 |
---|---|
1 | 讀請求,即下載 |
2 | 寫請求,即上傳 |
3 | 表示數據包,即DATA |
4 | 確認碼,即ACK |
5 | 錯誤 |
因為udp的數據包不安全,即發送方發送是否成功不能確定,所以TFTP協議中規定,為了讓服務器知道客戶端已經接收到了剛剛發送的那個數據包,所以當客戶端接收到一個數據包的時候需要向服務器進行發送確認信息,即發送收到了,這樣的包成為ACK(應答包)
為了標記數據已經發送完畢,所以規定,當客戶端接收到的數據小於516(2字節操作碼+2個字節的序號+512字節數據)時,就意味着服務器發送完畢了
TFTP數據包格式如下:
---------------------代碼案例實現---------------------

1 #coding=utf-8 2 3 #進行對應包的引用 4 from socket import * 5 6 import struct 7 8 import sys 9 10 #創建一個套接字進行網絡通信 11 soc =socket(AF_INET,SOCK_DGRAM) 12 13 #獲取對應傳遞的ip地址參數 14 strIp=sys.argv[1] 15 16 #元組,放對應的ip地址和端口號 17 addr=(strIp,69) 18 19 #參數:現在文件的名字 20 strName=sys.argv[2] 21 22 #進行組包,提交給TFTP服務 23 sendData=struct.pack("!H"+str(len(strName))+"sb5sb",1,strName,0,"octet",0) 24 25 #數據的發送 26 soc.sendto(sendData,addr) 27 28 #初始化文件管理對象 29 fil='' 30 31 #下載后的文件重命名 32 filName=sys.argv[2] 33 34 while True: 35 #接受服務器的相應數據(內容,(ip,端口)) 36 recvData,recvAddr=soc.recvfrom(1024) 37 38 #對接受的數據進行處理 39 opkey=struct.unpack("!HH",recvData[:4]) 40 41 print(opkey) 42 43 #變量存儲序號 44 pNum=opkey[1] 45 46 #3判斷,從服務器上下載的數據 47 if opkey[0]==3: 48 #第一次數據傳遞時,進行對應的文件的創建 49 if pNum==1: 50 fil=open(filName,"w") 51 #數據的寫入 52 fil.write(recvData[4:]) 53 54 if len(recvData)<516: 55 56 fil.close() 57 print("下載完成!") 58 break 59 60 #5判斷,TFTP服務器出現錯誤 61 if opkey[0]==5: 62 print("運行錯誤!") 63 break 64 65 #組包 66 ackData=struct.pack("!HH",4,pNum) 67 68 soc.sendto(ackData,recvAddr) 69 soc.close()
---------------------附件struct表--------------------