怎麼有效理解可靠數據傳輸?
要想理解可靠數據傳輸(Reliable Data Transfer),那麼不妨結合與其相對的概念——不可靠數據傳輸進行理解。
1.什麼是可靠數據傳輸服務?什麼是可靠數據傳輸協議?
比如我們要實現這樣的一組通信,發送方通過一個網路協議給接收方發送一些數據分組,接收方有可能接收到了全部數據,也可能因為各種原因只接收到了部分數據分組或者根本沒有收到任何數據分組。即使收到了全部的數據分組,但可能這些分組是有序的(或者說可以通過一些操作恢復為發送時的順序)可以得到完整的消息(message),也有可能是無序的,無法恢復出完整的信息。即使數據包是完整的、有序的,有可能在某些地方因為信道有雜訊或者其他緣故出現一些差錯,導致數據上出了偏差。
協議要保證的不僅僅是發送方可以發數據,同時也會對接收方將接收到怎樣的數據做出一定的保證,這才是完整的通信。
Thus, to support these applications, something has to be done to guarantee that the data sent by one end of the application is delivered correctly and completely to the other end of the application. If a protocol provides such a guaranteed data delivery service, it is said to provide reliable data transfer.
分組可能會在網路中丟失、損壞,應用層可能對網路通信有所要求,不允許出現這種差錯,必須保證接收方的應用收到了完整且正確的數據,這種服務就是可靠數據傳輸服務。
如果一個協議可以確保發送端發送了怎樣的數據,那麼接收端就必然能接收到怎樣的數據,那麼就可以說這個協議提供了可靠數據傳輸服務,這個協議是可靠的,反之則是不可靠的。
類比一個比較形象的場景,一個記者去現場報道國家主席接見現任特首,那麼這個記者就相當於一個通信協議,如果能保證把所有的信息都完整、真實、無差錯地報道出來,讓觀眾、讀者可以通過她的報道真實感受現場情景,那麼她就提供了可靠的數據傳輸服務,如果她可能故意問一些沒有質量且水平低下的引導性問題,丟失一些信息沒有完全報道,夾帶私貨,把無中生有的事再重複一遍,宣傳上就出現了偏差,她就是不可靠的記者(協議)。
2.為什麼形容一個協議是可靠/不可靠的?為什麼說TCP是可靠的,UDP是不可靠的,IP也是不可靠的?
TCP服務模型除了面向連接以外,也提供可靠數據傳輸服務。
The communicating processes can rely on TCP to deliver all data sent without error and in the proper order. When one side of the application passes a stream of bytes into a socket, it can count on TCP to deliver the same stream of bytes to the receiving socket, with no missing or duplicate bytes.
通過TCP協議的通信進程可以無差錯地以正確的順序傳送所有數據。當一方的應用向套接字傳送位元組流時,它可以通過TCP向接收套接字傳送完全相同的位元組流而沒有丟失或者冗餘的位元組。
而同樣是傳輸層的重要協議UDP則不提供可靠傳輸服務,僅僅提供最小服務(minimal services),是無連接的。與之相對,無法保證接收套接字接收到的位元組流是完整的、無差錯的、有序的。
傳輸層之下的網路層,主要使用的是網際網路協議(IP協議)。IP協議是一個儘力而為(best-effort)的傳送協議,只實現通信方之間邏輯上的連接,IP協議只能儘力去傳送通信雙方的報文段,而不作出任何保證(完整性、正確性、有序性)
2.1 為什麼可以同時允許可靠/不可靠數據傳輸服務的存在?
協議棧中只要有協議提供可靠數據傳輸服務,那麼整個協議棧提供的服務就是可靠的。僅僅看網路層和傳輸層,UDP/IP架構是不可靠的,TCP/IP則是可靠的,很容易理解,這是一個「或/析取」的關係。假設整個協議棧各層由構成,表示第層所使用的協議,其值為是否提供可靠數據傳輸服務,那麼整個協議棧的可靠性可以表示為,當然這是個簡單粗暴的表達形式,實際上不是每層都有真正意義上的唯一協議,而且各層之間並非完全獨立。
在實際上的通信實現中,選取怎樣的協議,設計怎樣的協議棧,協議本身特性固然重要,但也有考慮通信需求的進程。說具體一些的例子,一般常用的應用涉及的也就是TCP和UDP的選擇,當然現實中還是使用TCP較多,因為大多數應用對數據的完整性、正確性有很高的要求,比如郵件服務/文件下載,但是對吞吐量和時間卻沒什麼要求,而有些應用比如視頻遊戲/即時通訊對實時性的要求非常高,對數據丟失卻是可以容忍的,視頻聊天的時候清晰度不高或者出現小規模馬賽克,略顯失真不是什麼大事,所以這個時候選用UDP協議更合適。
還是沿用上面的類比,傳輸層協議就像記者一樣,每個記者的技能點不一樣,一般情況下我們當然會偏愛知識水平高、立場客觀真實的西方記者,所以他的出勤會比較多比較著名。那麼香港記者經驗不足太膚淺、年輕不足以報道全部內容,她就一無是處嗎?不是的,她就像UDP,不存在任何擁塞控制而且輕量簡單(simple),跑的比誰都快,善於弄大新聞,對於實時性很高的新聞事件讓她去也很合適。
因此應用層上的每個協議都會根據需求選擇與之對應的傳輸層協議。
3.怎樣實現可靠數據傳輸?
對於底層信道完全可靠的情況,只需要調用跟著基本法來,接到上層調用就做一系列操作(打包之類的)把數據發給下層,接收方對應層協議收到下層的調用就將數據做些操作然後發給上層協議,其他的就不需要考慮了。
我們已經在2.1提到,IP是不可靠的,但是可以依靠上層的協議(如TCP)使這個使用IP協議的通信變得可靠,這就好比記者在採訪現場引導出了一些不符合積極向上的個人形象的言辭,但是沒關係,上層還有編輯和其他審核人員,他們的專業技能可以保證把通訊稿寫的符合基本法,那麼宣傳上就不會出現偏差。
現在要解決的問題就是怎樣在不可靠的網路層協議之上實現可靠的傳輸層協議。這裡以在IP上實現的TCP為例。
3.1 差錯檢測
包括奇偶校驗、校驗和、CRC等方法判斷收到的數據分組是否損壞,如果不能校正那就丟棄分組。
3.2ACK確認
這是在不可靠底層信道上加入的一種反饋機制,由接收方發送確認消息。發送方發送數據,接收方接收到了以後發了ACK表示「我已經收到了,可以繼續發了」,就像發了一個「支持XXXX嗎?」對方回答「吼啊」你才可以繼續提問,如果你問的那麼熱情對方一句話也不說,這就不好了,雖然不排除無可奉告的可能,但是也不能再繼續問下去了,這個模式就是停止等待(stop-and-wait)協議的思想,只有得到肯定的確認才能繼續發送數據。除了肯定確認ACK表示確認收到以外,還有否定確認NAK,用來表示某個數據沒有收到,比如滑動窗口協議中用的就是NAK,意思就是「沒聽說過」。
發送方收到了接收方發來的ACK/NAK後自己也要判斷的,然後再把接收方丟失的數據分組(無論是在信道上丟失的還是因為出了偏差所以主動丟棄的)重傳一遍。
以上其實就差不多是停止等待協議的基本內容了。
3.3 序號
但是ACK/NAK也可能在傳輸過程中被損壞,這時候就需要引入序號(sequence number),接收方可以通過檢查收到的數據分組的序號發現哪些分組沒有收到、哪些分組冗餘了。發送ACK/NAK反饋時也可以指定Seq表示需要重傳哪些分組或者繼續往下發送哪些分組。序號的引入也讓傳送的效率大大提升,不用像停止等待那種樸素(naive)方法受限於當前的分組戰戰兢兢,可以以流水線傳送數據。
4.後記
「如何理解可靠數據傳輸」這個問題實在太大,僅僅從概念上來講就已經非常大了,我不知道題主需要的是具體哪方面的內容,所以把最基礎的部分寫出來了,事實上比如重傳中的超時機制也是很重要的,雖然涉及了一些最基礎的元素,但是基礎的方法比如退回N步(Go-back-N)、選擇重傳(SR)、滑動窗口之類也都很重要,但是我的篇幅和精力有限,無法兼顧,只能帶你進門,剩下的學習要你自己去完成。這還僅僅是概念,源碼閱讀和實際應用也需要你自己多多考慮一下。
很慚愧,只做了一些微小的工作。
References[1] Velten, David, R. M. Hinden, and Jack Sax. Reliable data protocol. No. RFC 908. 1984.
[2] Kurose, James F. Computer Networking: A Top-Down Approach Featuring the Internet, 3/E. Pearson Education India, 2005.
推薦閱讀:
※瀏覽器能夠使用一次TCP連接多次發起http請求,那麼瀏覽器是怎麼區分這多個請求的響應的?
※學習網路編程,想寫個聊天伺服器練練,想實現客戶端之間的通信,但是卡殼了?
※1.1.1.1 是哪裡的 IP?
※為什麼TCP的MSS協商沒有按照小的來?
※關於IP數據報轉發的疑問?