TFTP的工作都是由客戶端發(fā)起一個RRQ或者WRQ開始的。這里分別以WRQ和RRQ為例,講述讀寫的工作過程,以及錯誤處理等內(nèi)容。
用S表示Server,C表示Client。
1. WRQ工作流程
l S在端口為69的UDP上等待C發(fā)出寫文件請求包
l C通過UDP發(fā)送符合TFTP請求格式的WRQ包給S。從UDP包角度看,該UDP包的源端口由C隨意選擇,而目標(biāo)端口則是S的69。
l S收到C的這個請求包后,需發(fā)送ACK給C。對于寫請求包,S發(fā)送的ACK包確認(rèn)號為0。
l C發(fā)送DATA數(shù)據(jù)給S,S接收數(shù)據(jù)并寫文件
l 當(dāng)C發(fā)送的DATA數(shù)據(jù)長度小于512字節(jié)時,S認(rèn)為這次WRQ請求完成
這里我們要明確一點,如果有多個C同時向S發(fā)起請求的話,S如何正確發(fā)送包到對應(yīng)的C呢。
在TFTP中,一次請求中所有包的源和目標(biāo)都由Transfer ID(TID)來標(biāo)示。TFTP規(guī)定TID值就是UDP包中的源和目標(biāo)端口。也就是說,一次請求過程中,S和C通過UDP包的源和目標(biāo)端口來判斷這個包是不是發(fā)給自己的。
以WRQ為例,C向S的69端口發(fā)送一個文件請求包,這個文件請求包中UDP的源端口號為C的TID(假設(shè)C選擇4845作為它的TID),目標(biāo)端口為69(這個時候由于請求還未接受,所以這次請求的UDP包中目標(biāo)端口不是TID)。S收到這個請求后,將另外采用一個UDP端口(應(yīng)該另啟動了一個UDP Socket)假設(shè)為4849來回復(fù)這個請求的ACK。這樣,這個回復(fù)的UDP包的源端口就是S的TID(=4849),目標(biāo)就是C的UDP端口(TID=4845)。以后,這次請求的后續(xù)所有包都在端口為4845和4849中來往。
上述過程隱含了一定程度上的容錯處理。例如,C收到一個TID不是4849的包,則認(rèn)為這個包是錯誤的。
另外,S對于每個請求,都要采用一個不重復(fù)的新的UDP端口號作為它的TID,也就是說,S上同時存在的n個請求的TID都將不同。
這里再介紹下TFTP的回復(fù)ACK機制。雖然TFTP中有指定的ACK包作為回應(yīng),但在普遍意義上,DATA包和ERROR包都可以作為上一次發(fā)送包的響應(yīng)。
一般來說,C發(fā)送了一個非結(jié)束DATA包給S,如果在超時時間內(nèi),C未收到S發(fā)送的ACK,則C繼續(xù)發(fā)送這個DATA直到S回復(fù)ACK。這種情況是比較好理解的。
但假如S回復(fù)了上一個非結(jié)束DATA包ACK后,C在S的超時時間內(nèi)沒有發(fā)送下一個DATA包,則S將繼續(xù)發(fā)送這個ACK。從這個角度看,S等待的這個新DATA包是對上一次ACK的確認(rèn)。
2. RRQ的工作流程
RRQ和WRQ類似。
l S在端口為69的UDP上等待C發(fā)出讀文件請求包
l C通過UDP發(fā)送符合TFTP請求格式的RRQ包給S。
l S收到C的這個請求包后,將直接發(fā)送DATA包給C,這個DATA包中含S選擇的TID作為UDP的源端口和C的TID作為UDP目標(biāo)端口,起始包號為1。
l C接收來自S的DATA包并回復(fù)ACK。直到請求完成
3. 連接和錯誤處理
UDP實際上沒有連接的概念。但從上面分析的RRQ和WRQ看,S在69端口上等待請求,而且S總是生成一個新的UDP來完成和C的交互。這個過程和TCP的listen以及Accept非常類似。所以TFTP把這種交互也稱作connection。只不過這種連接是隱含在請求中的。
一般情況下,連接的建立由一次成功的請求來發(fā)起,當(dāng)最后一個DATA包發(fā)送完畢并且ACK回復(fù)了后,則連接正常關(guān)閉。在傳輸過程中,如果出現(xiàn)錯誤,假設(shè)S向C發(fā)送了一個ERROR包,如果C收到ERROR包,則連接關(guān)閉。如果C沒有收到ERROR包,則需要啟動ERROR超時檢測機制。需要強調(diào)的是對于ERROR包,S和C都不會重傳也不需要ACK確認(rèn)。
TFTP建議在連接正常關(guān)閉的情況,S可在發(fā)送確認(rèn)結(jié)束DATA包的ACK后稍等片刻后再關(guān)閉連接。例如,當(dāng)C發(fā)送結(jié)束DATA包后,S回復(fù)ACK后再等一段時間才關(guān)閉。再次等待時間中,如果ACK包丟失,C將再次發(fā)送結(jié)束DATA包或者超時處理。S如果又收到一次結(jié)束DATA包后,就知道ACK包丟失了。S可以關(guān)閉連接也可以再次發(fā)送ACK包。
任何傳輸起自一個讀取或?qū)懭胛募恼埱螅@個請求也是連接請求。如果服務(wù)器批準(zhǔn)此請求,則服務(wù)器打開連接,數(shù)據(jù)以定長512字節(jié)傳輸。每個數(shù)據(jù)包包括一塊數(shù)據(jù),服務(wù)器發(fā)出下一個數(shù)據(jù)包以前必須得到客戶對上一個數(shù)據(jù)包的確認(rèn)。如果一個數(shù)據(jù)包的大小小于512字節(jié),則表示傳輸結(jié)束。如果數(shù)據(jù)包在傳輸過程中丟失,發(fā)出方會在超時后重新傳輸最后一個未被確認(rèn)的數(shù)據(jù)包。通信的雙方都是數(shù)據(jù)的發(fā)出者與接收者,一方傳輸數(shù)據(jù)接收應(yīng)答,另一方發(fā)出應(yīng)答接收數(shù)據(jù)。大部分的錯誤會導(dǎo)致連接中斷,錯誤由一個錯誤的數(shù)據(jù)包引起。這個包不會被確認(rèn),也不會被重新發(fā)送,因此另一方無法接收到。如果錯誤包丟失,則使用超時機制。錯誤主要是由下面三種情況引起的:不能滿足請求,收到的數(shù)據(jù)包內(nèi)容錯誤,而這種錯誤不能由延時或重發(fā)解釋,對需要資源的訪問丟失(如硬盤滿)。TFTP只在一種情況下不中斷連接,這種情況是源端口不正確,在這種情況下,指示錯誤的包會被發(fā)送到源機。這個協(xié)議限制很多,這是都是為了實現(xiàn)起來比較方便而進行的。通過下邊的圖片來了解tftp協(xié)議的通信流程: