TCP協議實現原理

TCP協議實現原理

TCP協議是端到端的傳輸控制協議,之所以是“端到端”的協議,是因爲”路由“是由IP協議負責的,TCP協議負責爲兩個通信端點提供可靠性保證,這個可靠性不是指一個端點發送的數據,另一個端點肯定能收到(這顯然是不可能的),而是指,數據的可靠投遞或者故障的可靠通知。

TCP的可靠性通過以下方式來保證:
1.超時重傳:TCP每發送出一個報文段後,都會啓動一個定時器,對目的端傳回的確認信息進行確認計時,超時後便重傳。
2.確認信號:當TCP收到一個來自TCP的報文段後,便會發送回一個確認信號。
3.檢驗和:TCP將始終保持首部和數據的檢驗和,如果收到的報文段的檢驗和有差錯,便將其丟棄,希望發送端超時重傳。
4.重新排序:由於IP數據報的達到可能失序,因此TCP將會數據進行重新排序,以正確的順序交給應用層。
5.丟棄重複:由於IP數據報有可能重複,因此TCP將會丟棄重複的數據。
6.流量控制:TCP連接的兩端都有固定大小的緩衝區空間,TCP接受端只允許對端發送本端緩衝區能容納的數據。

TCP提供流量控制。在雙方進行交互時,會彼此通知自己目前接收緩衝區最多可以接收的數據量(通告窗口),以此確保發送方發送的數據不會溢出接收緩衝區。 


TCP數據包主要包括:
1. SYN包:請求建立連接的數據包
2. ACK包:迴應數據包,表示接收到了對方的某個數據包
3. PSH包:正常數據包
4. FIN包:通訊結束包
5. RST包: 重置連接
導致TCP協議發送RST包的原因:
   1)SYN 數據段指定的目的端口處沒有接收進程在等待。
   2)TCP協議想放棄一個已經存在的連接。
   3)TCP接收到一個數據段,但是這個數據段所標識的連接不存在。
接收到RST數據段的TCP協議立即將這條連接非正常地斷開,並嚮應用程序報告錯誤。 
6. URG包: 緊急指針

一次完的TCP通訊包括:建立連接、數據傳輸、關閉連接
建立連接(三次握手):
1.客戶端通過向服務器端發送一個SYN來建立一個主動打開,作爲三路握手的一部分。
2.服務器端應當爲一個合法的SYN回送一個SYN/ACK。
3.最後,客戶端再發送一個ACK。這樣就完成了三路握手,並進入了連接建立狀態。
數據傳輸:
1.發送數據端傳輸PSH數據包
2.接收數據端回覆ACK數據包
關閉連接(四次分手):
1. 一端主動關閉連接。向另一端發送FIN包。
2. 接收到FIN包的另一端迴應一個ACK數據包。
3. 另一端發送一個FIN包。
4. 接收到FIN包的原發送方發送ACK對它進行確認。 

三次握手,四次分手:

TCP狀態轉換圖:

說明(netstat可查看狀態):

CLOSED: 初始狀態。

LISTEN: 服務器端的某個SOCKET處於監聽狀態,可以接受連接了。

SYN_RCVD: 服務器接受到了SYN報文。

SYN_SENT: 客戶端已發送SYN報文。

ESTABLISHED:連接已經建立了。

FIN_WAIT_1:當SOCKET在ESTABLISHED狀態時,它想主動關閉連接,向對方發送了FIN報文, 此時該SOCKET即進入到FIN_WAIT_1狀態。而當對方迴應ACK報文後,則進入到FIN_WAIT_2狀態,當然在實際的正常情況下,無論對方 何種情況下,都應該馬上回應ACK報文,所以FIN_WAIT_1狀態一般是比較難見到的,而FIN_WAIT_2狀態還有時常常可以用netstat看到。

FIN_WAIT_2:上面已經詳細解釋了這種狀態,實際上FIN_WAIT_2狀態下的SOCKET,表示半連接,也即有一方要求close連接,但另外還告訴對方,我暫時還有點數據需要傳送給你,稍後再關閉連接。

TIME_WAIT: 表示收到了對方的FIN報文,併發送出了ACK報文,就等2個MSL(最大生存時間)值(RFC建議2分鐘,Berkeley傳統使用30s)後即可回到CLOSED可用狀態了。如果FIN_WAIT_1狀態下,收到了對方同時帶FIN標誌和ACK標誌的報文時,可以直接進入到TIME_WAIT狀態,而無須經過FIN_WAIT_2狀態。
TIME_WAIT狀態存在兩個理由:
1.可靠地實現TCP連接的終止
2.允許老的重複分解在網絡中消逝
執行主動關閉的一端都會進入TIME_WAIT狀態,Linux下高併發的Squid服務器,TCP TIME_WAIT套接字數量經常達到數萬,服務器很容易被拖死。通過修改Linux內核參數,可以減少服務器的TIME_WAIT套接字數量。

CLOSING: 這種狀態比較特殊,實際情況中應該是很少見,屬於一種比較罕見的例外狀態。正常情況下,當你發送 FIN報文後,按理來說是應該先收到(或同時收到)對方的ACK報文,再收到對方的FIN報文。但是CLOSING狀態表示你發送FIN報文後,並沒有收 到對方的ACK報文,反而卻也收到了對方的FIN報文。什麼情況下會出現此種情況呢?其實細想一下,也不難得出結論:那就是如果雙方幾乎在同時close 一個SOCKET的話,那麼就出現了雙方同時發送FIN報文的情況,也即會出現CLOSING狀態,表示雙方都正在關閉SOCKET連接。

CLOSE_WAIT: 這種狀態的含義其實是表示在等待關閉。怎麼理解呢?當對方close一個SOCKET後發送 FIN報文給自己,你係統毫無疑問地會迴應一個ACK報文給對方,此時則進入到CLOSE_WAIT狀態。接下來呢,實際上你真正需要考慮的事情是察看你是否還有數據發送給對方,如果沒有的話,那麼你也就可以close這個SOCKET,發送FIN報文給對方,也即關閉連接。所以你在CLOSE_WAIT 狀態下,需要完成的事情是等待你去關閉連接。

LAST_ACK: 被動關閉一方在發送FIN報文後,最後等待對方的ACK報文。當收到ACK報文後,也即可以進入到CLOSED可用狀態了。
 

用下面這條語句可以查看linux服務器的狀態:
netstat -n | awk '/^tcp/ {++Status[$NF]} END {for(name in Status) print name, Status[name]}'
TIME_WAIT 15
CLOSE_WAIT 6
ESTABLISHED 141

或者這條命令也行:ss | awk 'NR>1 {++S[$1]} END {for(a in S) print a, S[a]}'

TCP發送數據包過程:
1. 應用程序write數據到發送緩衝區:如果套接口發送緩衝區容不下應用程序的所有數據,並且應用進程是阻塞的,應用進程將被掛起,直到所有的數據都拷貝到套接口緩衝區。

2. TCP根據MSS(Maxitum Segment Size)指對數據分段發送。MSS就是TCP數據包每次能夠傳輸的最大數據分段。爲了達到最佳的傳輸效能TCP協議在建立連接的時候通常要協商雙方的 MSS值,這個值TCP協議在實現的時候往往用MTU(最大傳輸單元,以太網MTU爲1500)值代替(需要減去IP數據包包頭的大小20Bytes和 TCP數據段的包頭20Bytes)所以往往MSS爲1460。通訊雙方會根據雙方提供的MSS值最小值確定爲這次連接的最大MSS值。

 

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章