網路滴神,TCP!

張小云的部落格發表於2020-07-31

 TCP在網路協議(網路協議見這篇文章)中是非常重要的,要說有多重要的話,那就像珍珠奶茶的奶茶一樣。

1. 三次握手

 TCP在進行資料的傳輸之前必須先建立連線,建立之後才能進行資料的傳輸,那麼所謂的建立連線是怎麼回事呢?來看下其三次握手。

三次握手

  1. 客戶端傳送SYNseq序列號,SYN為標識位,意思為請求同步,seq是此次包的序列號,序列號是單調遞增的,作用是保證傳輸的可靠性,在丟包的時候能確定丟的是哪個包。

  2. 服務端收到訊息之後,傳送確認的資訊,包括標識位SYN和ACK(表確認作用)、確認資訊ack=客戶端傳送的seq+1,seq=自己的seq。seq和ack的確認機制知道確認的是哪個包。

  3. 客戶端收到服務端的確認訊息(也是請求同步的資訊)之後,回覆其同步訊息,傳送ACK=1和ack=服務端的seq+1還有自己的seq(值為第一次的seq+1,要單調遞增),此時客戶端這邊的連線已經完成了。

  4. 服務端接收到客戶端的訊息之後,服務端這邊的連線也完成,至此三次握手圓滿結束,接下來就可以傳輸資料了。

 三次握手的流程並不複雜,概括就是:客戶端向服務端傳送同步請求,服務端確認並向客戶端傳送同步請求,客戶端確認,連線完成。

 但是在這簡單的流程中有幾個問題需要思考:

  • 為什麼需要三次握手?

  • 服務端有超時重傳機制嗎?確認包傳送之後一段時間沒收到響應會重發嗎,還是等待客戶端重發包。

  • 客戶端收到服務端的確認訊息之後能傳送資料嗎,即第二次握手完成的時候客戶端能向服務端傳送資料嗎?

 上面這些問題是不是除了第一個其他的都沒想過?你可能會說,"那肯定啊,誰沒事去想這玩意,我學TCP都是為了面試的時候能夠把三次握手四次揮手說出來。"

 哼!對於這種想法,我只能說:

同道中人

 不過如果想造火箭,自己總不能是一顆汽車的輪子吧(布加迪威龍除外),所以必要的思考很重要。那來看看這幾個問題

  • 為什麼要三次握手?

    答:因為四這個數字不吉利。

    打頭

     開個玩笑,麻煩把磚頭收一收。首先我們得理解TCP是雙方的連線,也就是說只有確定客戶端和服務端的傳送和接收都是沒問題的這個連線才算完成。那來看下,第一次握手略過,第二次握手也就是客戶端接收到服務端的確認訊息時,這裡證明了兩個問題:

    1. 服務端的確認訊息中的ack是自己的seq+1,說明服務端收到了自己剛才發的包並且能夠明白。
    2. 自己收到確認訊息說明服務端的傳送端正常,自己的接收端正常。

     到第二次握手這裡已經證明了三個所需條件:客戶端的傳送和接收正常、服務端的傳送正常。還少一個服務端的接收,所以客戶端要再發一次給服務端的確認包,讓服務端也知道其傳送和接收是正常的,所以總共是三次。

  • 服務端有超時重傳機制嗎?

     有的,如剛才所說,TCP是雙端的協議,服務端是接收方也是傳送方,所以是有超時重傳的機制。比如說第三次握手客戶端向服務端傳送訊息時由於網路原因丟包了,那麼服務端一段時間後沒收到訊息就會重發。

  • 客戶端收到服務端的確認訊息之後能傳送資料嗎?

     意思就是說,在第二次握手完成後,客戶端能不能向服務端傳送資料。在回答這個問題之前,我先問一個問題,這時候客戶端這邊已經確認傳送和接收沒問題了,現在不能發,什麼時候能發呢?所以是可以的,就算丟包也有確認應答和重發機制來保證。

 三次握手結束之後,就可以進行資料的傳輸,這裡有長連線短連線之分。可能放在這裡比較陌生,但是另一個協議——HTTP的長連線和短連線應該都知道了,其本質就是TCP的長連線和短連線,而且作用是一樣的,短連線在傳送一次資料後就進行關閉,長連線則保持直到主動選擇關閉分開。

 說到分開,讓我不由得想起那一年四月,夕陽淌在她的臉上,她用纖細的手指挽起了耳邊的秀髮,轉過頭對我說:"我們之間已經沒有什麼能給對方的了,總要一個人先開口,就像TCP'四次揮手'一樣!"

醒醒,程式猿哪裡有女朋友。

女朋友呢X

2. 四次揮手

 不知道怎麼開頭,先給大家看個寶貝吧。

四次揮手2

 看了這張圖都是字母,即便你告訴我這就是四次揮手,但這就像JOJO一樣,一開始我是難以接受的。沒有關係,魯迅說過,"四次揮手比起機械的記憶,嘗試去理解帶來的價效比可能要高得多。"

 我們一開始也說過,TCP是雙方的協議,所以雙方要有溝通,這樣才能正確的關閉通道。而TCP的溝通,是這樣的:

客戶端:"我這邊資料發完了,我要把我這邊的傳送通道關了,你看下你那邊有沒有什麼問題。"

服務端:"嗯,我資料接收完了,你關吧,我把我這邊的接收通道也關了。"

okay,這樣客戶端關閉了傳送通道,服務端關閉了接收通道(注意,只能由傳送通道發起聊天)。過了一段時間後,服務端這邊的資料也都傳輸完了,他也想關閉了。

服務端:"我這邊的資料也發完了,我這邊把傳送通道關了就下班了,你還有什麼問題嗎?"

客戶端:"我這邊也接收完了,你關吧,我也把這邊的接收通道關了。等下下班後一起去修車嗎?"

此時客戶端還不能直接關完走人,因為他不知道修車地址啊(可惡)。說錯了,是他擔心服務端沒收到他的訊息,那需要等他個2MSL吧,如果服務端真的沒收到會重新發資訊過來的,到時候我再發一次就行。

 到這裡再回過頭來看上面那張圖。emem,是不是完全搞懂了。

原來是這樣07e0tj

 (不理解再慢慢看看)個人覺得圖中最重要的應該是TIME_WAIT狀態,以及為什麼要等2MSL,順便說下MSL是報文單位,不想懂可以理解為另一種意義的秒。

 所以以後再被問為什麼要四次揮手?你就說為了一起修車(不是)。

3. TCP是如何保證可靠性的

 當我們被問到TCP和UDP的區別時,我們總會回答:"TCP是可靠的,而UDP是不可靠的。"但TCP為什麼是可靠的,是怎麼保證其可靠性的可能就沒那麼多人知道了。

  1. 校驗和
  2. 序號和確認應答:
  3. 超時重傳
  4. TCP不處理重複的包
  5. ARQ協議
  6. 流量控制
  7. 擁塞控制

 上面這些就是TCP可靠性的基石,來看下這些基石長什麼樣。

  • 校驗和

     將頭部和資料通過一個演算法得到一個結果,這個結果就是校驗和。校驗和是防止包在傳輸的過程中被修改,接收端接收到包也會通過特定的演算法來檢測校驗和是否能對上。

  • 序號和確認應答

     這在上方三次握手的時候也有涉及到,意思就是在傳送方每次傳送的包都是有序號的,如果包丟了,就要重新發下這個序號對應的包,而確認應答機制可以做到讓傳送端知道該重發的是哪個包。

    丟包三次確認

     如上圖,在傳輸的過程中,如果中途丟了一個包,例如上圖的11-20的包,那麼接收方就會不斷的確認1-10的包,即便收到21-30的包,傳送方收到三次這樣的確認之後便判定包已丟失進行重發。

  • 超時重傳

     這就沒什麼好說的,無論是服務端還是客戶端在傳送之後都會啟動一個定時器,一段時間之後沒收到確認定時器就會觸發重發。

  • TCP不處理重複的包

     假設現在網路很慢,客戶端發了訊息之後一直沒收到回覆,就會重發,兩次或者更多次,而且發的是同一個序號的包,那麼這時服務端可能先收到一個包,進行處理後傳送確認訊息,之後又收到了同一個序號的包,此時便不做處理,直接丟棄,對於後面來的相同序號的包也執行相同的操作。

  • 連續ARQ協議

     TCP採用的是連續ARQ協議,大致的意思就是說,有資料不馬上發,等待湊齊一定數量或者到了最大等待時間再發,湊齊一定的數量稱為一組,而連續ARQ協議就是說不用等待確認訊息再發下一組,可以連續發多組。(ARQ協議還有另外一種,有興趣的可以自己瞭解下)

  • 流量控制

     在介紹流量控制之前,先提出一個問題:服務端有沒有可能出現接收不過來的情況?肯定有,不然我接下來的內容怎麼寫。

     那麼如果出現這樣的情況,會有怎麼樣的後果呢?

     服務端處理不過來,給客戶端的響應就會變慢,而客戶端收不到響應觸發超時重傳,哦吼,服務端本來就忙不過來,你還一直施加壓力,這不是讓服務端往死路逼嘛。

    做不到aai

     而流量控制,就是為了解決這種問題的。那麼流量控制究竟做了什麼呢?

     首先,傳送方和接收方雙發之間都維護了一個視窗,叫滑動視窗。接收方的視窗規定了還能接收多少資料,而傳送方的視窗則規定了還能傳送多少資料。接收方在回覆確認資訊的時候會將其能接收的大小發給傳送方,傳送方的視窗大小則取最小值Math.min{接收視窗大小,網路視窗大小(下個節點講)}。如果接收視窗的大小為0,那麼傳送方將不再傳輸資料,而是採用傳送探測包的形式檢測是否能繼續傳送資料。

  • 擁塞控制

     假設一個場景:

     客戶端發出了一個包,由於網路原因,導致了重發,但還是得不到響應,所以就不斷的重發,在這停住,然後把視野抽出來,看到有幾億個客戶端如此,繼續放送,現在會發生什麼呢?

     原本網路由於某些原因可能只有一點堵塞,但是由於n個客戶端進行了多次的重發操作,導致一下子就擁堵了起來,擁堵又會導致更多的客戶端超時而重發,從而進入一個惡性迴圈,這,自然是不行的。

     那咋辦呢?還能咋辦,遇事不決,限流解決。限流要限多少呢?無論定多少都感覺會錯,那從1開始逐漸逐漸往上升,總能有一個是對的吧?好想法!!!於是便有了慢啟動演算法,見下圖。

    慢啟動
                (此圖片來源網路,若有侵權聯絡我刪除)

    首先,傳送方不是一下子傳送所有資料,而是從小事做起,先發一個,如果正常那麼發兩倍,如此如此,直到到了一個閾值,如上圖中的16,此時不能再兩倍發了(因為再這樣很容易就超時),所以+1發,就這樣一直到到超時。如果發生了超時,閾值調整為發生超時時的一半,並且傳送發從1開始按照上方的演算法繼續走。這就是慢啟動演算法。

     注意傳送方能發的包大小還得看另一個引數——接收方的接收視窗大小,見上方流量控制的介紹。傳送方的傳送資料大小=min{接收方接收視窗,慢啟動演算法網路視窗},也就是兩個的最小值。


     有了上面這些,還有誰能質疑TCP的可靠性呢?

還有誰5k05k748

如果覺得文章對你有幫忙,希望關注沒事。[雙手合十]

本文為部落格園文章,點此跳轉

參考:

https://blog.csdn.net/sinat_36629696/article/details/80740678

https://www.cnblogs.com/taoshihan/p/11215289.html

https://www.cnblogs.com/zxiner/p/7203192.html

相關文章