TCP/IP協議詳解(二):創建和關閉鏈接

做者: remcarpediem
聯繫方式:segmentfaultcsdn簡書git

本文轉載請註明做者、文章來源,連接,版權歸做者全部。github

 看了酷殼網站上的《TCP 的那些事兒》系列文章,有一點很受啓發:鍛鍊一下本身是否使用較少的篇幅將TCP協議講解清楚。通常的同窗寫博文,可能像攤大餅同樣,篇幅較多而且羅嗦。我之前寫文章時也是這個習慣,因此但願在之後的博文寫做過程當中,儘可能使用比較短的篇幅來說完想要講的內容。
 爲了節約你的時間,本片文章主要講解一下內容:面試

  • TCP鏈接的創建和關閉segmentfault

  • TCP報文的ack number和 seq number的含義服務器

TCP狀態機

咱們都說TCP是面向鏈接的傳輸協議,可是網絡傳輸都是沒有鏈接的,包括TCP也是同樣。TCP所謂的「鏈接」,其實就是通信雙方維護的一個「鏈接狀態」,讓它看上去像是有鏈接同樣。因此,TCP的狀態轉移是很是重要的。網絡

 TCP的不一樣狀態和狀態轉移構成了所謂的TCP狀態機,以下圖所示。咱們先在介紹一下其中的幾個術語和狀態
TCP狀態機併發

  • 主動打開(active open)是指客戶端發送第一個SYN報文,它主動發起創建TCP鏈接的請求。tcp

  • 被動打開(passive open)是指服務端接受第一個SYN報文而且發回一個SYN報文,它響應創建TCP鏈接的請求。網站

  • SYN-SENT是指客戶端發送第一個SYN報文並等待接受服務端SYN+ACK報文時的狀態,一旦接受到SYN+ACK報文,客戶端狀態就變爲創建鏈接(ESTABLISHED)了。spa

  • SYN-RECEIVED是指服務端接受到第一個SYN報文併發回SYN+ACK報文等待客戶端ACK報文時的狀態,一旦接受到客戶端發送的ACK報文,服務端狀態就變成了創建鏈接。

  • FIN-WAIT-1是指首先但願關閉TCP鏈接的一端的狀態,當這一段發送FIN報文並等待ACK報文時,它就處於這個狀態下。當這一端接受到ACK報文時,它的狀態就變成了FIN-WAIT-2。

  • FIN-WAIT-2是指已經關閉本身這端TCP鏈接的一端等待接受另外一端FIN報文的狀態。等到接受到另一端的FIN報文,它的狀態就會變成TIME-WAIT。

  • CLOSE-WAIT是指首先收到FIN報文一端的狀態,這一端知道另外一端已經要關閉TCP鏈接了,可是本身這一端還未關閉TCP。

  • LAST-ACK是指首先收到FIN報文一端的狀態,這一端也要關閉TCP鏈接了,而且向另外一端發送了FIN報文。

sequence number和acknowledge number

 sequence number(以後簡稱爲seq)是用來標識從TCP發端到TCP收端發送的數據字節流,它表示在這個報文段中的第一個數據字節的序號。第一條報文的seq爲TCP協議本身計算出來的數值ISN,之後的報文的seq爲INS加上已經發送數據的長度,好比第一條報文的seq爲x,length爲100,那麼下一條帶有數據的報文的seq爲x+101。
 而acknowledge number(以後簡稱爲ack)是表示發送確認的一端所指望收到的下一個序號,所以ack是上次成功接收報文的seq數值加一。只有ACK標誌爲1時,ack纔有效。須要注意的是,TCP有些報文是不包含數據字節流信息的,那麼它就不會影響到下一個報文的seqence number。在上一端的例子中,一端接受到這個seq爲x,長度爲100的報文以後,須要發送一個帶有ACK標誌的報文,其ack值爲x+101。

TCP創建鏈接和關閉鏈接

 TCP創建鏈接和關閉鏈接是TCP協議中比較重要的一部分,也是面試常常會涉及的部分,咱們在這裏就來詳細講解一下TCP創建鏈接和關閉鏈接過程當中的每一步報文和其目的。
TCP創建和關閉鏈接

 TCP創建鏈接和關閉鏈接的過程也被稱爲三次握手和四次握手,其中涉及兩軍通信問題。由於網絡通信是不可靠的,因此你沒法知道本身發送的報文另一端是否收到,因此必須等待對方發送一個確認接受的報文;對於另一方也是如此,另一方也不清楚本身發送的確認接受報文是否被接受到,因此也但願對方再發送一個確認報文。可是在不可靠的通訊中,無論幾回握手(發送報文)都是有風險的,由於永遠沒法確認最後一次通訊被送達。通常來講,握手次數達到3就能夠保證通訊信息被正確傳達。

 客戶端首先發送一個帶有SYN標誌的報文給服務端,seq爲ISN,就是初始化的Sequence Number。如圖所示,client發送的SYN報文的seq爲x。客戶端發送這個報文的目的是通知服務端本身但願創建一個TCP鏈接。
 服務端接受到客戶端發送的SYN報文,須要返回一個帶有SYN和ACK標誌的報文,它的seq爲服務器端計算得到的ISN,也就是y。它的ack數值是已經收到報文的seq數值+1,也就是x+1。服務器端發送這個報文來通知客戶端本身已經收到客戶端但願創建鏈接的報文,而且贊成創建鏈接。
 客戶端接受到服務端的報文,發送一個帶有ACK標誌的報文,它的ack數值爲y+1。客戶端發送這個報文是爲了通知服務端本身已經收到了它的報文,能夠進行數據傳輸了。客戶端發送完這個報文以後,默認TCP鏈接已經創建,就能夠直接開始發送數據報文了。
 服務端接受到客戶端發送的ACK報文以後,就能夠直接發送數據啦。

 因爲TCP是全雙工的協議,也就是說兩端能夠同時進行數據傳輸,因此,TCP鏈接的關閉在兩端都關閉以後才正式關閉。當一端已經沒有能夠傳輸的數據時,就會發送帶有FIN標記的報文,向另外一端表示本身不會在傳輸數據啦。接受到另外一端的ack報文以後,這一端就不會在發送數據報文(也就是tcp負載)了。可是ack等控制信息報文仍是會發送的。也就是說,兩端的FIN報文不必定是連在一塊兒的,服務端可能很早就發送FIN報文了,可是客戶端能夠在服務端發送FIN報文以後繼續發送數據報文,而後在發送FIN報文。 如圖所示,client先發送帶有FIN標誌的報文給服務端,表面本身這端已經無數據能夠發送了,但願關閉TCP鏈接。報文的seq爲x+2,ack爲y+1。 服務端接受到這個報文以後發送帶有ACK標誌的報文,其ack爲(x+2)+1,也就是x+3。 服務端無數據發送以後,也向客戶端發送帶有FIN標誌的報文,seq爲y+1。 客戶端接受到該報文以後,發送一個帶有ACK標誌的報文,其ack爲y+2。

相關文章
相關標籤/搜索