主頁 > 軟體設計 > 清華老師終于把TCP協議講清楚了

清華老師終于把TCP協議講清楚了

2021-12-09 07:59:28 軟體設計

TCP協議

TCP協議的特點是:面向連接、位元組流和可靠傳輸,

使用TCP協議通信的雙方必須先建立連接,然后才能開始資料的讀寫,雙方都必須為該連接分配必要的內核資源,以管理連接的狀態和連接上資料的傳輸,TCP連接是全雙工的,即雙方的資料讀寫可以通過一個連接進行,完成資料交換之后,通信雙方都必須斷開連接以釋放系統資源,

  • TCP協議采用回傳確認機制,即發送端發送的每個TCP報文段都必須得到接收方的應答,才認為這個TCP報文段傳輸成功,

  • TCP協議采用超時重傳機制,發送端在發送出一個TCP報文段之后啟動定時器,如果在定時時間內未收到應答,它將重發該報文段,

  • TCP報文段最終是以IP資料報發送的,而IP資料報到達接收端可能亂序、重復,所以TCP協議還會對接收到的TCP報文段重排、整理,再交付給應用層

TCP會將資料放到緩沖區當中,接收端應用程式可以一次性將TCP接識訓沖區中的資料全部讀出,也可以分多次讀取,但是UDP每發送一個資料包,接收端必須及時針對每一個UDP資料報執行讀操作(通過recvfrom系統呼叫),否則就會丟包,

image.png

image.png

TCP頭部結構

image.png

  • 16位埠號(port number):告知主機該報文段是來自哪里(源埠)以及傳給哪個上層協議或應用程式(目的埠)的,進行TCP通信時,客戶端通常使用系統自動選擇的臨時埠號,而服務器則使用知名服務埠號,所有知名服務使用的埠號都定義在/etc/services檔案中,

  • 32位序號(sequence number):一次TCP通信(從TCP連接建立到斷開)程序中某一個傳輸方向上的位元組流的每個位元組的編號,假設主機A和主機B進行TCP通信,A發送給B的第一個TCP報文段中,序號值被系統初始化為某個隨機值ISN(Initial Sequence Number,初始序號值),那么在該傳輸方向上(從A到B),后續的TCP報文段中序號值將被系統設定成ISN加上該報文段所攜帶資料的第一個位元組在整個位元組流中的偏移,例如,某個TCP報文段傳送的資料是位元組流中的第1025~2048位元組,那么該報文段的序號值就是ISN+1025,另外一個傳輸方向(從B到A)的TCP報文段的序號值也具有相同的含義,

  • 32位確認號(acknowledgement number):用作對另一方發送來的TCP報文段的回應,其值是收到的TCP報文段的序號值加1,假設主機A和主機B進行TCP通信,那么A發送出的TCP報文段不僅攜帶自己的序號,而且包含對B發送來的TCP報文段的確認號,反之,B發送出的TCP報文段也同時攜帶自己的序號和對A發送來的報文段的確認號,


  • 4位頭部長度(header length):標識該TCP頭部有多少個32bit字(4位元組),因為4位最大能表示15,所以TCP頭部最長是60位元組,

  • 6位標志位包含如下幾項:

    • URG標志,表示緊急指標(urgent pointer)是否有效,
    • ACK標志,表示確認號是否有效,我們稱攜帶ACK標志的TCP報文段為確認報文段,
    • PSH標志,提示接收端應用程式應該立即從TCP接識訓沖區中讀走資料,為接收后續資料騰出空間(如果應用程式不將接收到的資料讀走,它們就會一直停留在TCP接識訓沖區中),
    • RST標志,表示要求對方重新建立連接,我們稱攜帶RST標志的TCP報文段為復位報文段,
    • SYN標志,表示請求建立一個連接,我們稱攜帶SYN標志的TCP報文段為同步報文段,
    • FIN標志,表示通知對方本端要關閉連接了,我們稱攜帶FIN標志的TCP報文段為結束報文段,

  • 16位視窗大小(window size):是TCP流量控制的一個手段,這里說的視窗,指的是接收通告視窗(Receiver Window,RWND),它告訴對方本端的TCP接識訓沖區還能容納多少位元組的資料,這樣對方就可以控制發送資料的速度,

  • 16位校驗和(TCP checksum):由發送端填充,接收端對TCP報文段執行CRC演算法以檢驗TCP報文段在傳輸程序中是否損壞,注意,這個校驗不僅包括TCP頭部,也包括資料部分,這也是TCP可靠傳輸的一個重要保障,

  • 16位緊急指標(urgent pointer):是一個正的偏移量,它和序號欄位的值相加表示最后一個緊急資料的下一位元組的序號,因此,確切地說,這個欄位是緊急指標相對當前序號的偏移,不妨稱之為緊急偏移,TCP的緊急指標是發送端向接收端發送緊急資料的方法,

image.png

TCP連接

image.png

TCP三次握手

image.png

  1. 客戶端向服務器發送一個連接請求,將標志位SYN置為1,隨機產生一個值seq=J,并將該資料包發送給服務器,等待服務器確認,
  2. 服務器收到資料包后由標志位SYN=1知道Client請求建立連接,Server將標志位SYN和ACK都置為1,ack=J+1,隨機產生一個值seq=K,并將該資料包發送給Client以確認連接請求,Server進入SYN_RCVD狀態,
  3. 客戶端檢查標志位,確認連接建立,回傳資料包,ACK=1,此時已經可以攜帶資料

TCP四次揮手

image.png

由于TCP連接時全雙工的,因此,每個方向都必須要單獨進行關閉,這一原則是當一方完成資料發送任務后,發送一個FIN來終止這一方向的連接,收到一個FIN只是意味著這一方向上沒有資料流動了,即不會再收到資料了,但是在這個TCP連接上仍然能夠發送資料,直到這一方向也發送了FIN,首先進行關閉的一方將執行主動關閉,而另一方則執行被動關閉

  1. Client發送一個FIN,用來關閉Client到Server的資料傳送,Client進入FIN_WAIT_1狀態,
  2. Server收到FIN后,發送一個ACK給Client,確認序號為收到序號+1,Server進入CLOSE_WAIT狀態,
  3. Server發送一個FIN,用來關閉Server到Client的資料傳送,Server進入LAST_ACK狀態,
  4. Client收到FIN后,Client進入TIME_WAIT狀態,接著發送一個ACK給Server,確認序號為收到序號+1,Server進入CLOSED狀態,完成四次揮手

TCP超時重傳

客戶端在長時間未收到回應報文時會重傳報文,例如,重傳時間間隔由/proc/sys/net/ipv4/tcp_syn_retries內核變數所定義,每次重連的超時時間都增加一倍,在5次重連均失敗的情況下,TCP模塊放棄連接并通知應用程式,

TCP狀態轉移

TCP連接的任意一端在任一時刻都處于某種狀態,當前狀態可以通過netstat命令查看

image.png

客戶端狀態

客戶端通過connect系統呼叫主動與服務器建立連接,connect系統呼叫首先給服務器發送一個同步報文段,使連接轉移到SYN_SENT狀態,此后,connect系統呼叫可能因為如下兩個原因失敗回傳:

  • 如果connect連接的目標埠不存在(未被任何行程監聽),或者該埠仍被處于TIME_WAIT狀態的連接所占用,則服務器將給客戶端發送一個復位報文段,connect呼叫失敗,
  • 如果目標埠存在,但connect在超時時間內未收到服務器的確認報文段,則connect呼叫失敗,

connect呼叫失敗將使連接立即回傳到初始的CLOSED狀態,如果客戶端成功收到服務器的同步報文段和確認,則connect呼叫成功回傳,連接轉移至ESTABLISHED狀態,

當客戶端執行主動關閉時,它將向服務器發送一個結束報文段,同時連接進入FIN_WAIT_1狀態,若此時客戶端收到服務器專門用于確認目的的確認報文段,則連接轉移至FIN_WAIT_2狀態,當客戶端處于FIN_WAIT_2狀態時,服務器處于CLOSE_WAIT狀態,這一對狀態是可能發生半關閉的狀態,此時如果服務器也關閉連接(發送結束報文段),則客戶端將給予確認并進入TIME_WAIT狀態,

服務器狀態

服務器通過listen系統呼叫進入LISTEN狀態,被動等待客戶端連接,因此執行的是所謂的被動打開,服務器一旦監聽到某個連接請求(收到同步報文段),就將該連接放入內核等待佇列中,并向客戶端發送帶SYN標志的確認報文段,此時該連接處于SYN_RCVD狀態,如果服務器成功地接收到客戶端發送回的確認報文段,則該連接轉移到ESTABLISHED狀態,ESTABLISHED狀態是連接雙方能夠進行雙向資料傳輸的狀態,

當客戶端主動關閉連接時(通過close或shutdown系統呼叫向服務器發送結束報文段),服務器通過回傳確認報文段使連接進入CLOSE_WAIT狀態,這個狀態的含義很明確:等待服務器應用程式關閉連接,通常,服務器檢測到客戶端關閉連接后,也會立即給客戶端發送一個結束報文段來關閉連接,這將使連接轉移到LAST_ACK狀態,以等待客戶端對結束報文段的最后一次確認,一旦確認完成,連接就徹底關閉了,

TCP擁塞控制

滑動視窗

為了解決可靠傳輸以及包亂序的問題,TCP 引入滑動視窗的概念,在傳輸程序中,client 和 server 協商接收視窗 rwnd,再結合擁塞控制視窗 cwnd 計算滑動視窗 swnd,在 Linux 內核實作中,滑動視窗 cwnd 是以包為單位,所以在計算 swnd 時需要乘上 mss(最大分段大小),

[公式]

滑動視窗包含 4 部分:

  • 已收到 ack 確認的資料;
  • 已發還沒收到 ack 的;
  • 在視窗中還沒有發出的(接收方還有空間);
  • 視窗以外的資料(接收方沒空間),

滑動后的示意圖如下(收到 36 的 ack,并發出了 46-51 的資料):

擁塞控制

RTT:RTT——Round Trip Time,也就是一個資料包從發出去到回來的時間,這樣發送端就大約知道需要多少的時間,

擁塞的發生是因為網路上的包太多導致路由器總是丟包,擁塞控制是快速傳輸的基礎,TCP不能忽略網路上發生的事情,而無腦地一個勁地重發資料,對網路造成更大的傷害,對此TCP的設計理念是:TCP不是一個自私的協議,當擁塞發生的時候,要做自我犧牲,就像交通阻塞一樣,每個車都應該把路讓出來,而不要再去搶路了, 一個擁塞控制演算法一般包括慢啟動演算法擁塞避免演算法快速重傳演算法快速恢復演算法四部分,

慢啟動演算法

慢啟動的意思是,剛剛加入網路的連接,一點一點地提速,不要一上來就像那些特權車一樣霸道地把路占滿,新同學上高速還是要慢一點,不要把已經在高速上的秩序給搞亂了,

慢啟動的演算法如下(cwnd全稱Congestion Window):

1)連接建好的開始先初始化cwnd = 1,表明可以傳一個MSS大小的資料,

2)每當收到一個ACK,cwnd++; 呈線性上升

3)每當過了一個RTT,cwnd = cwnd*2; 呈指數讓升

4)還有一個ssthresh(slow start threshold),是一個上限,當cwnd >= ssthresh時,就會進入“擁塞避免演算法”

所以,我們可以看到,如果網速很快的話,ACK也會回傳得快,RTT也會短,那么,這個慢啟動就一點也不慢,下圖說明了這個程序,

擁塞避免演算法

前面說過,還有一個ssthresh(slow start threshold),是一個上限,當cwnd >= ssthresh時,就會進入“擁塞避免演算法”,一般來說ssthresh的值是65535,單位是位元組,當cwnd達到這個值時后,演算法如下:

1)收到一個ACK時,cwnd = cwnd + 1/cwnd

2)當每過一個RTT時,cwnd = cwnd + 1

這樣就可以避免增長過快導致網路擁塞,慢慢的增加調整到網路的最佳值,很明顯,是一個線性上升的演算法,

擁塞狀態時的演算法

前面我們說過,當丟包的時候,會有兩種情況:

1)等到RTO超時,重傳資料包,TCP認為這種情況太糟糕,反應也很強烈,

    • sshthresh = cwnd /2
    • cwnd 重置為 1
    • 進入慢啟動程序

2)Fast Retransmit演算法,也就是在收到3個duplicate ACK時就開啟重傳,而不用等到RTO超時,

    • TCP Tahoe的實作和RTO超時一樣,
    • TCP Reno的實作是:

      • cwnd = cwnd /2
      • sshthresh = cwnd
      • 進入快速恢復演算法——Fast Recovery

上面我們可以看到RTO超時后,sshthresh會變成cwnd的一半,這意味著,如果cwnd<=sshthresh時出現的丟包,那么TCP的sshthresh就會減了一半,然后等cwnd又很快地以指數級增漲爬到這個地方時,就會成慢慢的線性增漲,我們可以看到,TCP是怎么通過這種強烈地震蕩快速而小心得找到網站流量的平衡點的,

快速恢復演算法

TCP Reno

快速重傳和快速恢復演算法一般同時使用,快速恢復演算法是認為,你還有3個Duplicated Acks說明網路也不那么糟糕,所以沒有必要像RTO超時那么強烈, 注意,進入快速恢復演算法之前,cwnd 和 sshthresh已被更新:

  • cwnd = cwnd /2
  • sshthresh = cwnd

然后,真正的Fast Recovery演算法如下:

  • cwnd = sshthresh + 3 * MSS (3的意思是確認有3個資料包被收到了)
  • 重傳Duplicated ACKs指定的資料包
  • 如果再收到 duplicated Acks,那么cwnd = cwnd +1
  • 如果收到了新的Ack,那么,cwnd = sshthresh ,然后就進入了擁塞避免的演算法了,

轉載請註明出處,本文鏈接:https://www.uj5u.com/ruanti/377034.html

標籤:其他

上一篇:四不幫你弄懂網路編程之最后一步

下一篇:對于程式員來說,2021年的冬天有點冷,互聯網大廠裁員,大齡程式員的出路又在哪里?

標籤雲
其他(157675) Python(38076) JavaScript(25376) Java(17977) C(15215) 區塊鏈(8255) C#(7972) AI(7469) 爪哇(7425) MySQL(7132) html(6777) 基礎類(6313) sql(6102) 熊猫(6058) PHP(5869) 数组(5741) R(5409) Linux(5327) 反应(5209) 腳本語言(PerlPython)(5129) 非技術區(4971) Android(4554) 数据框(4311) css(4259) 节点.js(4032) C語言(3288) json(3245) 列表(3129) 扑(3119) C++語言(3117) 安卓(2998) 打字稿(2995) VBA(2789) Java相關(2746) 疑難問題(2699) 细绳(2522) 單片機工控(2479) iOS(2429) ASP.NET(2402) MongoDB(2323) 麻木的(2285) 正则表达式(2254) 字典(2211) 循环(2198) 迅速(2185) 擅长(2169) 镖(2155) 功能(1967) .NET技术(1958) Web開發(1951) python-3.x(1918) HtmlCss(1915) 弹簧靴(1913) C++(1909) xml(1889) PostgreSQL(1872) .NETCore(1853) 谷歌表格(1846) Unity3D(1843) for循环(1842)

熱門瀏覽
  • 面試突擊第一季,第二季,第三季

    第一季必考 https://www.bilibili.com/video/BV1FE411y79Y?from=search&seid=15921726601957489746 第二季分布式 https://www.bilibili.com/video/BV13f4y127ee/?spm_id_fro ......

    uj5u.com 2020-09-10 05:35:24 more
  • 第三單元作業總結

    1.前言 這應該是本學期最后一次寫作業總結了吧。總體來說,對作業的節奏也差不多掌握了,作業做起來的效率也更高了。雖然和之前的作業一樣,作業中都要用到新的知識,但是相比之前,更加懂得了如何利用工具以及資料。雖然之間卡過殼,但總體而言,這幾次作業還算完成的比較好。 2.作業程序總結 相比前兩個單元,此單 ......

    uj5u.com 2020-09-10 05:35:41 more
  • 北航OO(2020)第四單元博客作業暨課程總結博客

    北航OO(2020)第四單元博客作業暨課程總結博客 本單元作業的架構設計 在本單元中,由于UML圖具有比較清晰的樹形結構,因此我對其中需要進行查詢操作的元素進行了包裝,在樹的父節點中存盤所有孩子的參考。考慮到性能問題,我采用了快取機制,一次查詢后盡可能快取已經遍歷過的資訊,以減少遍歷次數。 本單元我 ......

    uj5u.com 2020-09-10 05:35:48 more
  • BUAA_OO_第四單元

    一、UML決議器設計 ? 先看下題目:第四單元實作一個基于JDK 8帶有效性檢查的UML(Unified Modeling Language)類圖,順序圖,狀態圖分析器 MyUmlInteraction,實際上我們要建立一個有向圖模型,UML中的物件(元素)可能與同級元素連接,也可與低級元素相連形成 ......

    uj5u.com 2020-09-10 05:35:54 more
  • 6.1邏輯運算子

    邏輯運算子 1. && 短路與 運算式1 && 運算式2 01.運算式1為true并且運算式2也為true 整體回傳為true 02.運算式1為false,將不會執行運算式2 整體回傳為false 03.只要有一個運算式為false 整體回傳為false 2. || 短路或 運算式1 || 運算式2 ......

    uj5u.com 2020-09-10 05:35:56 more
  • BUAAOO 第四單元 & 課程總結

    1. 第四單元:StarUml檔案決議 本單元采用了圖模型決議UML。 UML檔案可以抽象為圖、子圖、邊的邏輯結構。 在實作中,圖的節點包括類、介面、屬性,子圖包括狀態圖、順序圖等。 采用了三次遍歷UML元素的方法建圖,第一遍遍歷建點,第二、三次遍歷設定屬性、連邊,實作圖物件的初始化。這里借鑒了一些 ......

    uj5u.com 2020-09-10 05:36:06 more
  • 談談我對C# 多型的理解

    面向物件三要素:封裝、繼承、多型。 封裝和繼承,這兩個比較好理解,但要理解多型的話,可就稍微有點難度了。今天,我們就來講講多型的理解。 我們應該經常會看到面試題目:請談談對多型的理解。 其實呢,多型非常簡單,就一句話:呼叫同一種方法產生了不同的結果。 具體實作方式有三種。 一、多載 多載很簡單。 p ......

    uj5u.com 2020-09-10 05:36:09 more
  • Python 資料驅動工具:DDT

    背景 python 的unittest 沒有自帶資料驅動功能。 所以如果使用unittest,同時又想使用資料驅動,那么就可以使用DDT來完成。 DDT是 “Data-Driven Tests”的縮寫。 資料:http://ddt.readthedocs.io/en/latest/ 使用方法 dd. ......

    uj5u.com 2020-09-10 05:36:13 more
  • Python里面的xlrd模塊詳解

    那我就一下面積個問題對xlrd模塊進行學習一下: 1.什么是xlrd模塊? 2.為什么使用xlrd模塊? 3.怎樣使用xlrd模塊? 1.什么是xlrd模塊? ?python操作excel主要用到xlrd和xlwt這兩個庫,即xlrd是讀excel,xlwt是寫excel的庫。 今天就先來說一下xl ......

    uj5u.com 2020-09-10 05:36:28 more
  • 當我們創建HashMap時,底層到底做了什么?

    jdk1.7中的底層實作程序(底層基于陣列+鏈表) 在我們new HashMap()時,底層創建了默認長度為16的一維陣列Entry[ ] table。當我們呼叫map.put(key1,value1)方法向HashMap里添加資料的時候: 首先,呼叫key1所在類的hashCode()計算key1 ......

    uj5u.com 2020-09-10 05:36:38 more
最新发布
  • 【中介者設計模式詳解】C/Java/JS/Go/Python/TS不同語言實作

    * 中介者模式是一種行為型設計模式,它可以用來減少類之間的直接依賴關系,
    * 將物件之間的通信封裝到一個中介者物件中,從而使得各個物件之間的關系更加松散。
    * 在中介者模式中,物件之間不再直接相互互動,而是通過中介者來中轉訊息。 ......

    uj5u.com 2023-04-20 08:20:47 more
  • 露天煤礦現場調研和交流案例分享

    他們集團的資訊化公司及研究院在一個礦區正在做智能礦山的統一平臺的 試點,專案投資大概1億,包括了礦山的各方面的內容,顯示得我們這次交流有點多余。他們2年前開始做智能礦山的規劃,有很多煤礦行業專家的加持,他們的描述是非常完美,但是去年底應該上線的平臺,現在還沒有看到影子。他們確實有很多場景需求,但是被... ......

    uj5u.com 2023-04-20 08:20:25 more
  • 《社區人員管理》實戰案例設計&個人案例分享

    設計是一個讓人夢想成真程序,開始編碼、測驗、除錯之前進行需求分析和架構設計,才能保證關鍵方面都做正確 ......

    uj5u.com 2023-04-20 08:20:17 more
  • 軟體架構生態化-多角色交付的探索實踐

    作為一個技術架構師,不僅僅要緊跟行業技術趨勢,還要結合研發團隊現狀及痛點,探索新的交付方案。在日常中,你是否遇到如下問題 “ 業務需求排期長研發是瓶頸;非研發角色感受不到研發技改提效的變化;引入ISV 團隊又擔心質量和安全,培訓周期長“等等,基于此我們探索了一種新的技術體系及交付方案來解決如上問題。 ......

    uj5u.com 2023-04-20 08:20:10 more
  • 【中介者設計模式詳解】C/Java/JS/Go/Python/TS不同語言實作

    * 中介者模式是一種行為型設計模式,它可以用來減少類之間的直接依賴關系,
    * 將物件之間的通信封裝到一個中介者物件中,從而使得各個物件之間的關系更加松散。
    * 在中介者模式中,物件之間不再直接相互互動,而是通過中介者來中轉訊息。 ......

    uj5u.com 2023-04-20 08:19:44 more
  • 露天煤礦現場調研和交流案例分享

    他們集團的資訊化公司及研究院在一個礦區正在做智能礦山的統一平臺的 試點,專案投資大概1億,包括了礦山的各方面的內容,顯示得我們這次交流有點多余。他們2年前開始做智能礦山的規劃,有很多煤礦行業專家的加持,他們的描述是非常完美,但是去年底應該上線的平臺,現在還沒有看到影子。他們確實有很多場景需求,但是被... ......

    uj5u.com 2023-04-20 08:19:07 more
  • 《社區人員管理》實戰案例設計&個人案例分享

    設計是一個讓人夢想成真程序,開始編碼、測驗、除錯之前進行需求分析和架構設計,才能保證關鍵方面都做正確 ......

    uj5u.com 2023-04-20 08:18:57 more
  • 軟體架構生態化-多角色交付的探索實踐

    作為一個技術架構師,不僅僅要緊跟行業技術趨勢,還要結合研發團隊現狀及痛點,探索新的交付方案。在日常中,你是否遇到如下問題 “ 業務需求排期長研發是瓶頸;非研發角色感受不到研發技改提效的變化;引入ISV 團隊又擔心質量和安全,培訓周期長“等等,基于此我們探索了一種新的技術體系及交付方案來解決如上問題。 ......

    uj5u.com 2023-04-20 08:18:49 more
  • 05單件模式

    #經典的單件模式 public class Singleton { private static Singleton uniqueInstance; //一個靜態變數持有Singleton類的唯一實體。 // 其他有用的實體變數寫在這里 //構造器宣告為私有,只有Singleton可以實體化這個類! ......

    uj5u.com 2023-04-19 08:42:51 more
  • 【架構與設計】常見微服務分層架構的區別和落地實踐

    軟體工程的方方面面都遵循一個最基本的道理:沒有銀彈,架構分層模型更是如此,每一種都有各自優缺點,所以請根據不同的業務場景,并遵循簡單、可演進這兩個重要的架構原則選擇合適的架構分層模型即可。 ......

    uj5u.com 2023-04-19 08:42:41 more