TCP為什么是個可靠的協議


  一直以來,我們都被告知TCP是可靠的。但為什么是可靠的,很多人都會說“三次握手、四次揮手”。然后我們就進入一個誤區:TCP可靠是因為它在建立鏈路時進行了“多次”地確認。然后又有人問,“多次確認就可靠了嗎?”專家想了一會,說:“這只是相對的……”

  回顧一下,網絡書籍里面有一個很著名的問題,“紅軍和藍軍通信聯合進攻山下的敵軍的例子,第一天紅軍發了條信息要藍軍第二天一起進攻,藍軍收到之后,發一條確認信息,但是藍軍擔心的是‘確認信息’如果也不可靠而沒有成功到達紅軍那里,那自己不是很危險?於是紅軍再發一條‘對確認的確認信息’,但同樣的問題還是不能解決,紅軍仍然不敢貿然行動。”這個問題簡直就是故意在諷刺“三次握手”。

 根據這個故事回到“三次握手”,客戶在第三次ACK后,他想,“萬一服務器沒有收到怎么辦呢?”這個問題只能讓服務器再發一個應答來解決,然后服務器就會遇到同樣的一個問題,如此不斷地糾結下去……而事實上,TCP連接建立時只到客戶第三次ACK就結束了,這能說是“可靠”的協議嗎?

  如果按照“紅軍藍軍問題”的思路想下去,那就沒出路了。就該問題目前的條件而言,是永遠沒有結果的,因為信息發送方在對方不應答的前提之下,永遠不能保證對方是否已經收到,不管信息發送多少次。實際打仗時,最終就只能演變成“默契”問題了,“默契”有沒有辦法用邏輯來解釋,不管大家知不知道,反正我是不知道的。

  那TCP難道是不可靠的?其實不然。理解的誤區就在網絡協議和行軍打仗的差異上。

  慶幸的是,網絡協議和軍隊打仗是不一樣的,軍隊打仗時如果不能確保消息的正確傳遞和步調同步,那是不能輕易出動的,人死不能復生啊。但是數據發送異常后可以重發,這不存在問題。另外,客戶端在發送數據時,只要確保服務器已經收到數據就可以了,不需要服務器關心客戶端是否收到應答。這一點也是和“紅軍藍軍問題”不一樣的,這就不會造成死循環的問題。

  具體理解一下,網絡協議中,客戶端和服務器在發送數據時並不要求兩端要同時發送數據,甚至兩端發送的數據內容也不存在必然的聯系。不像兩軍進攻,要講究目的相同,出發時間相同。細細分析,TCP在發送數據時,都只關心對端是否已經收到自己發送的數據,即只要收到對方對自己發送的數據確認就可以了。換句話說,每一端(客戶端或者服務器)都很“自私”,只保證對方已經收到自己發送的數據就OK了。

  按照上面的說法,分析一下TCP交互的過程。客戶要進入ESTABLISHED,因此,客戶端發送SYN告訴服務器要打開鏈路,收到ACK后,表示服務器已經同意了,OK,客戶進入ESTABLISHED狀態。只是客戶建立連接不行啊,服務器還沒進入ESTABLISHED狀態呢,所以服務器在應答時一並發送了自己的SYN,收到客戶端的ACK后,自己才進入ESTABLISHED狀態,然后才可以接受客戶端發過來的數據。

  然后,分析一下數據傳輸時,數據發送方在收到應答后,表示對方收到數據了,自己就可以將剛才發送過的數據清空了。無需再告訴對方,我已經收到你的應答了,沒有意義。同樣的,四次揮手也同樣符合上述說法。

  又要回到起初的問題了,“三次握手”第三個ACK應答丟失了怎么辦?現在應該很好理解,第三個ACK其實是對服務器SYN的應答,應答丟了,服務器就不得不重發SYN。又有人要問,萬一重發后還是沒ACK怎么呢,其實,這是沒關系的,這個時候服務器等待ACK超時,自然會把套接口關掉,置為異常狀態。如果后面客戶端發送的數據到達,服務器也會響應RST,來告訴客戶端這一異常,而不是ACK客戶端過來的數據。客戶端和服務器不需要像打仗那樣保持同步(一同進入ESTABLISHED),只要各自能夠兼容狀態不同步帶來的異常就可以了。

  最后回到最根本的問題,TCP是否是個可靠的協議,答案是肯定的。TCP保證的是自己的行為被別人確認,而不是確認別人的應答。這里所謂的行為便是“我要SYN”、“我要發送數據”、“我要FIN”……在網絡編程中,時刻存在着“主-從”關系,這兩者的地位不是固定的,誰發生了行為誰就是“主”,誰接受了行為就是“從”,“主”在乎的是“從”之后的應答,而“從”在乎的是“主”實際的行為。對於正常的行為與應答,他們就可取所需,完成一次正常的交互和狀態變遷;對於異常的行為,“從”不給出“主”最在乎的應答,給出相應的錯誤提示;對於異常的應答,“主”做出相應的反應(比如通知應用進程關閉套接字)。


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM