TCP

《網絡編程》中提到TCP的三個特點:面向連接、可靠、流式服務。現在具體看一下其特點。


一、TCP固定頭部結構


16位端口號:告知主機該報文段來自哪裏(源端口號)要傳給那個上層協議或應用程序(目的端口號)。

32位序號:一次TCP通信過程中某一個傳輸方向上的字節流的每個字節的編號。A發送給B的第一個報文段中,序號值被系統初始化爲某個隨機值ISN,後續在該方向上的TCP報文段的序號值被設置爲ISN加上該報文段所攜帶數據的第一個字節在整個字節流中的偏移。

32位確認號:另一方對TCP報文段的響應,其值是收到的TCP報文段的序號值加1。

4位頭部長度:標識該TCP頭部有多少個32位(即有多少行),因爲4位最大能表示15,所以TCP頭部最長是60字節。

6位標誌:

URG標誌:緊急指針是否有效。

ACK標誌:確認號是否有效。稱攜帶ACK標誌的TCP報文段爲確認報文段

PSH標誌:提示接收端應用程序應該立即從TCP接受緩衝區中讀走數據,爲接受後續數據騰出空間。TCP緩衝區  在網卡上,有大小限制,如果應用程序一直不讀取就會一直在緩衝區,影響後續數據。

RST標誌:表示要求對方重新建立連接。稱攜帶RST標誌的TCP報文段爲復位報文段

SYN標誌:請求建立連接。稱攜帶SYN標誌的TCP報文段爲同步報文段

FIN標誌:通知對方本段要關閉連接。稱攜帶FIN標誌的TCP報文段爲結束報文段

16位窗口大小:TCP流量控制的一個手段。這裏窗口指接收通告窗口。告訴對方本端的TCP緩衝區還能接收多大字節的數據,避免發過來接收不了,數據丟失。

16位校驗和:發送端填充,接收端對TCP報文段執行CRC算法檢驗TCP報文段在傳輸過程中是否損壞。不僅檢驗頭部也檢驗數據部分。

16位緊急指針:它和序號值相加表示最後一位緊急數據的下一字節的序號,這部分爲緊急數據先處理。


可以看出其可靠性:

1、32位序號:保證數據有序;

2、32位確認號與超時重傳機制:保證報文段不會丟失;

3、6位標誌:說明報文段的類型;

4、16位窗口大小:告訴對方本端TCP緩衝區還能容納多少字節的數據,這樣對方可以控制發送數據的速度,保證發送的數據流量不會超過容納範圍,也就保證了不會丟失數據;

5、校驗和:保證數據的準確性。


補充一下TCP的超時重傳機制。

TCP模塊爲每個TCP報文段都維護一個重傳定時器,該定時器在TCP報文段第一次被髮送時啓動,如果超過時間沒有收到對方確認,就重傳並重置定時器。至於超時多長時間重傳或重傳多少次,就看TCP的重傳策略。

每次重傳超時時間都增加一倍,因爲比如說第一次0.2s沒有成功,那再傳時0.2s也不會成功,所以增加一倍。當達到最大重傳次數,底層的IP和ARP開始接管,直到客戶端放棄連接。Linux有兩個重要的內核參數與TCP超時重傳相關:/proc/sys/net/ipv4/tcp_retries1(底層IP接管之前最少重傳的次數,默認值爲3)和/proc/sys/net/ipv4/tcp_retries2(放棄連接前TCP最多可以重傳的次數默認值爲15)。


二、面向連接

三次握手建立連接,四次揮手斷開連接。其具體過程如下:


三次握手:客戶端先發起連接,發送SYN(連接請求),然後服務器確認收到並同意建立連接,客戶端在進行確認。


爲什麼客戶端還要發送一次確認呢?

TCP有超時重傳機制,客戶端發送一次連接長時間沒有收到確認,客戶端會再次發送連接請求。如果第一次因爲報文段丟失沒有收到確認,第二次正常建立連接,數據傳輸後釋放連接;如果第一次是因爲報文段在某些網絡節點長時間滯留,以致於連接釋放以後纔到達服務器,本來這是一個已經失效的報文段,但是服務器收到以後,會誤認爲這是客戶端新發送的一次連接請求,服務器端發送確認報文段同意連接,如果沒有第三次確認,連接就建立了。但是客戶端並沒有發送連接請求,也不會發送數據,服務器就會一直等待,浪費資源。也就是說,客戶端再發送一次確認主要是爲了防止已失效的連接請求報文段突然又傳送到服務器端而產生錯誤。



TCP連接的釋放客戶端和服務器都可以先發起,這裏以客戶端發起斷開連接請求爲例。

客戶端先向服務器發送連接釋放報文段,並停止發送數據,主動關閉TCP連接。服務器收到連接釋放報文段後立即發出確認,但是服務器到客戶端方向的連接並未關閉,等服務器處理完所有數據後,給客戶端發送連接釋放報文段。客戶端收到後發送確認信息。

這裏有一點要注意,這是TCP連接還沒有釋放掉,必須經過2MSL(最長報文短壽命)時間後,大約2分鐘才能結束。


爲什麼必須在TIME_WAIT狀態等待2MSL的時間呢?

1、可靠地終止TCP連接。要保證最後一個ACK能夠到達,如果服務器端沒有沒有收到最後一個ACK,就會超時重傳,但是客戶端已經結束了,服務器沒有辦法正常的終止連接。

2、保證讓遲來的TCP報文段(已失效的報文段)有足夠的時間被識別並丟棄。在TIME_WAIT狀態時,無法使用該鏈接佔用的端口號建立新的連接。如果沒有TIME_WAIT狀態,遲來的報文段(已經失效的報文段)會出現在下一次的連接中,但實際上是應該被丟棄的。

因爲TCP報文段的最大生存時間是MSL,所以堅持2MSL時間可以確保網絡上兩個傳輸方向上尚未被收到的、遲到的TCP報文都已經消失(被中轉路由丟棄)。因此必須在TIME_WAIT狀態等待2MSL的時間。


三、狀態轉移


服務器

通過listen系統調用進入LISTEN狀態,被動等待客戶端連接;服務器一但監聽到某個連接請求,將其放入listen創建的隊列中,並向客戶端發送帶SYN標誌的確認報文段。此時該連接處於SYN_RCVD狀態。如果服務器成功收到客戶端發回的確認報文段,則轉移到ESTABLISHED狀態(連接雙方能夠進行雙向數據傳輸狀態)。

當客戶端主動請求關閉連接時,服務器通過返回確認報文段進入CLOSE_WAIT狀態(服務器應用程序關閉連接),服務器檢測到客戶端關閉連接後,也會立即給客戶端發送報文段關閉連接,進入LAST_ACK狀態,等待客戶端對結束報文段的最後一次確認。一旦完成連接就徹底關閉。

客戶端

通過connect系統調用主動與服務器建立連接。connect首先給服務器發送一個同步報文段,使連接轉移到SYN_SENT狀態。connect調用失敗返回到CLOSED狀態。客戶端成功收到服務器的同步報文段和確認,進入ESTABLISHED狀態。

當客戶端主動關閉時,向服務器發送一個結束報文段,同時進入FIN_WAIT1狀態,收到服務器的確認報文段進入FIN_WAIT2狀態。此時服務器發送結束報文段,客戶端進入TIME_WAIT狀態。

總的狀態轉移:







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