協議森林09 愛的傳聲筒 (TCP連接)

作者:Vamei 出處:http://www.cnblogs.com/vamei 歡迎轉載,也請保留這段聲明。謝謝!
 
TCP協議與"流"通信中,我們概念性的講解了TCP通信的方式。可以看到,TCP通信最重要的特徵是:有序(ordering)可靠(reliable)。有序是通過將文本流分段並編號實現的。可靠是通過ACK回覆和重複發送(retransmission)實現的。這一篇文章將引入TCP連接(connection)的概念。
 

TCP連接

網絡層在邏輯上提供了端口的概念。一個IP地址可以有多個端口。一個具體的端口需要IP地址和端口號共同確定(我們記爲IP:port的形式)。一個連接爲兩個IP:port之間建立TCP通信。(一個常用的比喻爲:TCP連接就像兩個人打電話, IP爲總機號碼,port爲分機號碼)
 
參與連接的如果是兩臺電腦,那麼兩臺電腦操作系統的TCP模塊負責建立連接。每個連接有四個參數(兩個IP,兩個端口),來表明“誰在和誰通話”。每臺電腦都會記錄有這四個參數,以確定是哪一個連接。如果這四個參數完全相同,則爲同一連接;如果這四個參數有一個不同,即爲不同的連接。這意味着,同一個端口上可以有多個連接。內核中的TCP模塊生成連接之後,將連接分配給進程使用。
 
一個端口上可以有多個連接
 
TCP連接是雙向(duplex)的。在TCP協議與"流"通信中,我們所展示的TCP傳輸是單向的。雙向連接實際上就是建立兩個方向的TCP傳輸,所以概念上並不複雜。這時,連接的每一方都需要兩個滑窗,以分別處理髮送的文本流和接收的文本流。由於連接的雙向性,我們也要爲兩個方向的文本流編號。這兩個文本流的編號相互獨立。爲文本流分段和編號由發送方來處理,回覆ACK則由接收的一方進行。
 

TCP片段的頭部格式

在深入TCP連接之前,我們需要對TCP片段的頭部格式有一些瞭解。我們知道,TCP片段分爲頭部數據。數據部分爲TCP真正傳輸的文本流數據。下面爲TCP片段的頭部格式:
來自wikipedia
先關注下面幾點:
1. 一個TCP頭部需要包含出發端口(source port)目的地端口(destination port)。這些與IP頭中的兩個IP地址共同確定了連接。
2. 每個TCP片段都有序號(sequence number)。這些序號最終將數據部分的文本片段整理成爲文本流。
3. ACK是一位(bit)。只有ACK位設定的時候,回覆號(Acknowledgement number)纔有效。ACK回覆號說明了接收方期待接收的下一個片段,所以ACK回覆號爲最後接收到的片段序號加1。
很多時候,ACK回覆“附着”在發送的數據片段中。TCP協議是雙向的。比如A和B兩個電腦。ACK回覆是接收方回覆給發送方 (比如A發送給B, B回覆A)。但同時,B也可以是發送方,B有可能有數據發送給A,所以B就把ACK回覆附着在它要發送給A的數據片段的頭部。這樣可以減少ACK所佔用的交通流量。一個片段可以只包含ACK回覆。一個純粹的ACK回覆片段不傳送文本流,所以不消耗序列號。如果有下一個正常的數據片段,它的序號將與純粹ACK回覆片段的序號相同。
(ACK回覆還可以“附着”在SYN片段和FIN片段)
4. ACK後面還有SYNFIN,它們也各佔據一位(bit)。我將在後面說明這兩位。
 

連接的建立

TCP協議與"流"通信中討論的TCP傳輸需要一個前提:TCP連接已經建立。然而,TCP連接從無到有需要一個建立連接的過程。建立連接的最重要目是讓連接的雙方交換初始序號(ISN, Initial Sequence Number)。根據TCP協議的規定,文本流的第一個片段的序號不能是確定的數字(比如說1)。連接的雙方各自隨機生成自己的ISN,然後再利用的一定方式讓對方瞭解。這樣的規定是出於TCP連接安全考慮:如果以一個確定的數字作爲初始的TCP序號,那麼其他人很容易猜出接下來的序列號,並按照正確的序號發送“僞裝”的TCP片段,以插入到文本流中。
ISN交換是通過SYN片段實現的。SYN片段由頭部的SYN位表明,它的序號爲發送方的ISN。該片段由連接的一方首先發給給另一方,我們將發送SYN的一方稱爲客戶(client),而接收SYN的一方稱爲服務器(server)。我們使用ISN(c)表示client一方的ISN,使用ISN(s)表示server一方的ISN。隨後,接收到SYN的server需要回復ACK,併發送出包含有server的ISN的SYN片段。下圖爲建立連接的過程,也就是經典的TCP三次握手(three-way handshaking)。兩條豎直線分別爲client和server的時間軸。每個箭頭代表了一次TCP片段的單向傳輸。
青色爲純粹的ACK片段。整個過程的本質是雙方互發含有自己的ISN的SYN片段。根據TCP傳輸的規則,接收到ISN的一方需要回復ACK,所以共計四片信息在建立連接過程中傳輸。之所以是三次握手 (而不是四次),是因爲server將發送SYN回覆ACK合併到一個TCP片段中。我們以client方爲例。client知道自己的ISN(也就是ISN(c))。建立連接之後,它也知道了對方的ISN(s)。此後,如果需要發送文本流片段,則編號爲ISN(c) + 1, ISN(c) + 2 ...。如果接收文本流片段,則期待接收ISN(s) + 1, ISN(s) + 2 ...。
連接建立之後,連接的雙方就可以按照TCP傳輸的方式相互發送文本流了。
 

連接的正常終結

一個連接建立之後,連接兩端的進程可以利用該連接進行通信。當連接的一方覺得“我講完了”,它可以終結連接中發送到對方方向的通信。連接最終通過四次握手(four-way handshaking)的方式終結,連接終結使用的是特殊片段FIN(FIN位爲1的片段)。
我們可以看到,連接終結的過程中,連接雙方也交換了四片信息(兩個FIN和兩個ACK)。在終結連接的過程中,TCP並沒有合併FIN與ACK片段。原因是TCP連接允許單向關閉(half-close)。也就是說,TCP連接關閉了一個方向的傳輸,成爲一個單向連接(half-duplex)。第二個箭頭和第三個箭頭傳遞必須分開,纔能有空隙在開放的方向上繼續傳輸。如果第二個箭頭和第三個箭頭合併在一起,那麼,隨着一方關閉,另一方也要被迫關閉。
第二和第三次握手之間,server可以繼續單向的發送片段給client,但client不能發送數據片段給server。
(上面的終結從client先發起,TCP連接終結也可以從server先發起。)
在Client發送出最後的ACK回覆,但該ACK可能丟失。Server如果沒有收到ACK,將不斷重複發送FIN片段。所以Client不能立即關閉,它必須確認Server接收到了該ACK。Client會在發送出ACK之後進入到TIME_WAIT狀態。Client會設置一個計時器,等待2MSL的時間。如果在該時間內再次收到FIN,那麼Client會重發ACK並再次等待2MSL。所謂的2MSL是兩倍的MSL(Maximum Segment Lifetime)。MSL指一個片段在網絡中最大的存活時間,2MSL就是一個發送和一個回覆所需的最大時間。如果直到2MSL,Client都沒有再次收到FIN,那麼Client推斷ACK已經被成功接收,則結束TCP連接。
TIME_WAIT State
發佈了14 篇原創文章 · 獲贊 11 · 訪問量 7萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章