TCP面向位元組流和報文段的關係是什麼?

TCP是面向位元組流的,把數據看做無結構的位元組流,但是又有TCP報文段的存在,而且如果看成位元組流的話,又是怎麼保證數據有序的呢?而使用java的socket介面的時候,伺服器端是直接從輸入流中讀出位元組數據,沒有涉及什麼報文段,數據亂序的問題,這些東西的關係到底是怎麼樣的?


法國政府委託人將自由女神按照從上到下,從左到右(類似電視機一幀圖像顯示方式)的順序編號,編號為1-300,編號1用1號箱子打包,編號2用2號箱子打包,以此類推,一共300個箱子,快遞公司並不關心箱子里裝的是啥,在他們眼裡這些都是貨物,只關心的是如何把這些貨物按照法國政府提交的編號順序(1,2,3…300)運輸到目的地,然後按照相同的編號順序(1,2,3…300)提交給美國政府,任務就算完成了。至於如何完成以上的任務(亂序、丟包重傳)則可以參考以下這個故事。

http://www.zhihu.com/question/53960871/answer/137346451

而基於TCP Socket編程,比如客戶端使用HTTP請求伺服器的主頁,伺服器生成了自己的主頁,一共300K byte數據,包括Header + Payload,為了更清晰說明問題,假設TCP最多一次只能發送1K byte的數據,伺服器端程序首先要將300K數據按照順序砍成300塊 (Segment),按照從頭到尾編號,1-300,然後調用send()函數300次,嚴格按照時間順序,第一次調用發編號1,第二次調用發編號2,…第三百次調用發編號300,這個不複雜,只要編寫一個循環程序(300次)即可,只要每次調用的返回值都OK,應用程序的任務就算完成了。

以上的編號1-300就是TCP segment編號,那位元組流的編號呢,就是 1,300000,其中 1-1000 位元組被編在1號TCP segment,1001-2000位元組編在2號segment,以此類推。

TCP不關心本地send()給自己的內容是啥(反正都是位元組),只關心時序,先發給自己的肯定先編號,後發的後編號,TCP本身只保證傳輸的順序,至於在伺服器端本地、客戶端本地的順序則由Receive()/ Send()時序來保證!


分清楚上下層的關係就簡單了。

TCP給上層提供了正序的保證送達且不重複服務,正序、不重複和可靠都是TCP層要完成的工作。所以上層看起來就是一個不間斷的數據流。


問題的關鍵在於TCP是有緩衝區,作為對比,UDP面向報文段是沒有緩衝區的。

TCP發送報文時,是將應用層數據寫入TCP緩衝區中,然後由TCP協議來控制發送這裡面的數據,而發送的狀態是按位元組流的方式發送的,跟應用層寫下來的報文長度沒有任何關係,所以說是流。

作為對比的UDP,它沒有緩衝區,應用層寫的報文數據會直接加包頭交給網路層,由網路層負責分片,所以是面向報文段的。


tcp協議棧,是通信協議兩端,維持的一個狀態機。狀態機需要考慮兩端數據流有序確認,超時,丟包重傳。可以通過Wireshark,tcpdump兩端抓包觀察,結合tcpip詳解這本書學習。如果懂編程的話,可以找lwip協議棧來學習,這方面資料也不少


這就是協議分層的意義。編程的時候只需要調用api,提供要傳輸的數據。報文的封裝,傳輸,糾錯等動作都由系統來實現。


推薦閱讀:

怎樣實時判斷socket鏈接狀態?
leader/follower, 半同步半非同步 和 事件驅動的關係是什麼?
你用socket寫過什麼有趣的程序?
Linux中本機和本機Socket通信會走網卡嗎?

TAG:互聯網 | 計算機網路 | Socket | TCPIP |