網絡基礎之--TCP協議

傳輸控制協議 TCP 概述

  • TCP 是面向連接的運輸層協議。

  • 每一條 TCP 連接只能有兩個端點(endpoint),每一條 TCP 連接只能是點對點的(一對一)。 

  • TCP 提供可靠交付的服務。

  •  TCP 提供全雙工通信。

  • 面向字節流。  

TCP 報文段的首部格式 

wKiom1ekiz6jD_IUAAB3CGv6UZY729.png


  • 源端口和目的端口字段——各佔 2 字節。端口是運輸層與應用層的服務接口。運輸層的複用和分用功能都要通過端口才能實現。  

  • 序號字段——佔 4 字節。TCP 連接中傳送的數據流中的每一個字節都編上一個序號。序號字段的值則指的是本報文段所發送的數據的第一個字節的序號。 

  • 確認號字段——佔 4 字節,是期望收到對方的下一個報文段的數據的第一個字節的序號。 

  • 數據偏移(即首部長度)——佔 4 位,它指出 TCP 報文段的數據起始處距離 TCP 報文段的起始處有多遠。“數據偏移”的單位是 32 位字(以 4 字節爲計算單位)。  

  • 保留字段——佔 6 位,保留爲今後使用,但目前應置爲 0。 

  • 緊急 URG —— 當 URG =1 時,表明緊急指針字段有效。它告訴系統此報文段中有緊急數據,應儘快傳送(相當於高優先級的數據)。 

  • 確認 ACK —— 只有當 ACK = 1 時確認號字段纔有效。當 ACK =0 時,確認號無效。 

  • 推送 PSH (PuSH) —— 接收 TCP 收到 PSH = 1 的報文段,就儘快地交付接收應用進程,而不再等到整個緩存都填滿了後再向上交付。  

  • 復位 RST (ReSeT) —— 當 RST =1 時,表明 TCP 連接中出現嚴重差錯(如由於主機崩潰或其他原因),必須釋放連接,然後再重新建立運輸連接。 

  • 同步 SYN —— 同步 SYN = 1 表示這是一個連接請求或連接接受報文。 

  • 終止 FIN (FINis) —— 用來釋放一個連接。FIN =1 表明此報文段的發送端的數據已發送完畢,並要求釋放運輸連接。 

    URG是通過置1來讓後面的緊急指針字段有效,從而讓報文段更先發送,而PSH是通過置1來告訴接收     方在接收到報文段後應該立即把數據發給上層而不是緩存起來。

    URG=1,緊急指針指向包內數據段的某個字節(數據從第一字節到指針所指字節就是緊急數據,不進入接     收緩衝就直接交給上層進程,餘下的數據要進入接收緩衝的),PSH=1就是把接收緩衝中排好序的那一     段數據交給上層

  • 窗口字段 —— 佔 2 字節,用來讓對方設置發送窗口的依據,單位爲字節。

  • 檢驗和 —— 佔 2 字節。檢驗和字段檢驗的範圍包括首部和數據這兩部分。在計算檢驗和時,要在 TCP 報文段的前面加上 12 字節的僞首部。

  • 緊急指針字段 —— 佔 16 位,指出在本報文段中緊急數據共有多少個字節(緊急數據放在本報文段數據的最前面)。  

  • 選項字段 —— 長度可變。TCP 最初只規定了一種選項,即最大報文段長度 MSS。MSS 告訴對方 TCP:“我的緩存所能接收的報文段的數據字段的最大長度是 MSS 個字節。” 

  注:MSS (Maximum Segment Size)是 TCP 報文段中的數據字段的最大長度。數據字段       加上 TCP 首部纔等於整個的 TCP 報文段。

  • 填充字段 —— 這是爲了使整個首部長度是 4 字節的整數倍。 

TCP 的連接建立(三次握手

第一次握手

wKiom1eklorw0euiAACDzQTClWs905.png

次握手

wKioL1eklovCTnBgAACdIDrSbJI177.png

第三次握手

wKiom1eklovT9rn2AACOprUfIng812.png

wKioL1ekloyyWRxJAACKdoBil2Q661.png

各階段的狀態

wKioL1ekloyRuQuBAACZd49ThPU484.png

各狀態的含意:
CLOSED: 表示初始狀態。 
LISTEN: 表示服務器端的某個SOCKET處於監聽狀態,可以接受連接了。 
SYN_RECV: 這個狀態表示接受到了SYN報文,在正常情況下,這個狀態是服務器端的SOCKET在建立TCP連接時的三次握手會話過程中的一箇中間狀態,很短暫,基本 上用netstat你是很難看到這種狀態的,除非你特意寫了一個客戶端測試程序,故意將三次TCP握手過程中最後一個ACK報文不予發送。因此這種狀態 時,當收到客戶端的ACK報文後,它會進入到ESTABLISHED狀態。 
SYN_SENT: 這個狀態與SYN_RECV遙想呼應,當客戶端SOCKET執行CONNECT連接時,它首先發送SYN報文,因此也隨即它會進入到了SYN_SENT狀 態,並等待服務端的發送三次握手中的第2個報文。SYN_SENT狀態表示客戶端已發送SYN報文。 
ESTABLISHED:表示連接已經建立了。


TCP 的連接釋放 (四次揮手

一次揮手

wKioL1ekmP-wRyGIAACgh3o0U_E233.png

第二次揮手

wKiom1ekmQChlcoWAACt9IzEH-8394.png

第三次揮手

wKioL1ekmQDDX3jGAACpd-o2BWw381.png

第四次揮手

wKioL1ekmQGBnPfCAACx7lajREY692.png

wKiom1ekmQHgPTDyAACzoxZeJ-I834.png

各階段的狀態

wKioL1ekmQHjMeugAADWDPZ1Ckk368.png

各狀態含義:
FIN_WAIT_1: 其實FIN_WAIT_1和FIN_WAIT_2狀態的真正含義都是表示等待對方的FIN報文。而這兩種狀態的區別 是: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報文,就等2MSL後即可回到CLOSED可用狀態了。如果FIN_WAIT_1狀態下,收到了對方同時帶 FIN標誌和ACK標誌的報文時,可以直接進入到TIME_WAIT狀態,而無須經過FIN_WAIT_2狀態。 
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可用狀態了。 


爲什麼是“三次握手”和“四次揮手



  • 爲什麼需要“三次握手”

在《計算機網絡》(謝希仁版)一書中講“三次握手”的目的是“爲了防止已失效的連接請求報文段突然又傳送到了服務端,因而產生錯誤”。

書中的例子是這樣的:“已失效的連接請求報文段”的產生在這樣一種情況下:client發出的第一個連接請求報文段並沒有丟失,而是在某個網絡結點長時間的滯留了,以致延誤到連接釋放以後的某個時間纔到達server。本來這是一個早已失效的報文段。但server收到此失效的連接請求報文段後,就誤認爲是client再次發出的一個新的連接請求。於是就向client發出確認報文段,同意建立連接。假設不採用“三次握手”,那麼只要server發出確認,新的連接就建立了。由於現在client並沒有發出建立連接的請求,因此不會理睬server的確認,也不會向server發送數據。但server卻以爲新的運輸連接已經建立,並一直等待client發來數據。這樣,server的很多資源就白白浪費掉了。採用“三次握手”的辦法可以防止上述現象發生。例如剛纔那種情況,client不會向server的確認發出確認。server由於收不到確認,就知道client並沒有要求建立連接。”。主要目的防止server端一直等待,浪費資源。

  • 爲什麼需要“四次揮手”

這是因爲在建立連接時,服務端的LISTEN狀態下的SOCKET當收到SYN報文的建連請求後,它可以把ACK和SYN(ACK起應答作用,而SYN起同步作用)放在一個報文裏來發送。但關閉連接時,當收到對方的FIN報文通知時,它僅僅表示對方沒有數據發送給你了;但未必你所有的數據都全部發送給對方了,所以你可以未必會馬上會關閉SOCKET,也即你可能還需要發送一些數據給對方之後,再發送FIN報文給對方來表示你同意現在可以關閉連接了,所以它這裏的ACK報文和FIN報文多數情況下都是分開發送的。


j_0027.gifj_0027.gifj_0027.gifj_0027.gifj_0027.gifj_0027.gifj_0027.gifj_0027.gifj_0027.gifj_0027.gifj_0027.gifj_0027.gifj_0027.gif

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