Linux 系列
文章目錄
- Linux 系列
- 前言
- 一、TCP協議的概念
- 1.1 TCP協議的特點
- 1.2 TCP又叫做傳輸控制協議
- 二、TCP協議段格式
- 2.1、TCP的流量控制----------窗口大小(16位)
- 2.2 TCP的確認應答機制
- 2.2.1 什么是確認應答機制
- 2.2.2 確認應答機制的優化
- 2.3 超時重傳機制
- 2.2 TCP協議的六個標志位
- 總結
前言
接下來的兩篇文章,我將系統講解TCP協議,涵蓋其核心概念與實現邏輯,內容包含TCP協議段格式、確認應答(ACK)機制、超時重傳機制、連接管理機制、滑動窗口、流量控制、擁塞控制、延遲應答、捎帶應答、面向字節流等具體實現細節。因內容體量較大,分兩篇展開介紹 。
一、TCP協議的概念
1.1 TCP協議的特點
下述特點,在后文中都會更詳細的介紹
- 連接導向性:TCP 是面向連接的運輸層協議。應用程序使用 TCP 前,需先建立 TCP 連接;數據傳輸完成后,要釋放已建立的連接 。
- 連接特性:每條 TCP 連接僅存在兩個端點,且連接模式為點對點(一對一),不支持多對多等復雜拓撲 。
- 可靠交付:TCP 提供可靠數據傳輸服務,經其連接傳送的數據,可保障無差錯、不丟失、不重復,且嚴格按序到達 。
- 全雙工通信:TCP 支持全雙工模式,通信雙方的應用進程可隨時發送數據。連接兩端均設有發送緩存與接收緩存,用于臨時存儲雙向傳輸的數據 。
- 面向字節流:TCP 里的“流”,指的是流入進程或從進程流出的字節序列,以字節為基本處理單元開展數據交互 。
1.2 TCP又叫做傳輸控制協議
在網絡通信建立前,應用程序創建的 TCP 套接字(sockfd)本質上是指向操作系統分配的socket 文件控制塊(Socket File Control Block),該控制塊內部維護著用于網絡數據傳輸的發送緩沖區和接收緩沖區。當應用層調用 write
、send
等發送函數時,實際執行的是將數據從用戶空間緩沖區拷貝至內核空間的 TCP 發送緩沖區(即傳輸層),后續的傳輸決策(包括發送時機、發送窗口大小、錯誤處理機制如超時重傳等)完全由 TCP 協議棧自主管理,由此TCP又被稱為傳輸控制協議。當應用層調用 read
、recv
等接收函數時,數據則是從內核空間的 TCP 接收緩沖區反向拷貝至用戶空間緩沖區。
應用層緩沖區,就是我們自己定義的臨時存儲數據的空間
當客戶端在給服務端發數據時,服務端依然可以給客戶端發數據,雙方是獨立的,所以TCP通信是全雙工的。
二、TCP協議段格式
在介紹這部分時,會粗略的介紹TCP的一部分實現機制,重要的部分后面會再次單獨介紹,下面我會分點對TCP組成字段一一介紹
TCP報文攜帶的有效載荷如何交付給上層
- 16位源端口:發送方主機進程綁定的端口號
- 16位目的端口:目的主機進程綁定的端口號
源端口保證發送的請求被接收后,接收主機可以得知該請求的來源。
目的端口保證發送的請求被接收后,該交付給該主機的哪個進程。
TCP報頭和報文如何分離
- 4位首部長度:用于標識 TCP 報文段中數據部分的起始位置距離報文段頭部起始處的字節偏移量。
由于選項長度是動態的,TCP實際首部長度不固定,而該字段以4字節為單位,,因此實際首部長度需通過 “字段值 ×4” 計算得出(例如字段值為 5 時,首部長度為 5×4=20 字節),該字段子表示范圍為【0000–1111】,所以有效數據長度=報文長度–實際首部長度這一樣就可以將二者進行分離。
2.1、TCP的流量控制----------窗口大小(16位)
此處簡略介紹
首先我們先以一個極端的例子,感受一下什么是流量控制:
當客戶端頻繁向服務端發送請求,而服務端處理能力不足時,若客戶端持續高速發送數據,會導致服務端接收緩沖區溢出,造成丟包。為避免這種情況,當服務端接收緩沖區接近滿負荷時,客戶端就應該降低發送速率或暫停發送。這種協調發送方與接收方數據處理速度的策略,稱為流量控制。
那么客戶端應該慢多少?是如何衡量的呢?或者說流量控制如何實現?
- 16位窗口大小:表示發送該TCP報文的接受窗口還可以接受多少字節的數據量。該字段用于TCP的流量控制。
在進行網絡通訊是,客戶端、服務端,都會將自己接收窗口的大小添加進自己的TCP報頭中,用來協商收發速度,接收方通過該字段動態通知發送方自己的接收能力,是 TCP 流量控制機制的關鍵實現方式,說白了這個16位窗口大小就是對方的接收緩沖區還剩多少空間。
2.2 TCP的確認應答機制
2.2.1 什么是確認應答機制
TCP實現數據可靠傳輸的基礎機制就是確認應答(ACK)機制, 發送方發出數據以后,接收方要給發送方一個回復,確認自己已經收到數據了,這樣的回復稱為ACK,確認應答報文。
在介紹這塊之前,首先我們要先知道為什么網絡通信不可靠:在網絡通信場景中,長距離數據傳輸面臨的挑戰不僅來自中間設備的處理限制,還包括物理鏈路中信號干擾的影響。當客戶端向服務器發送請求時,由于底層網絡(如IP協議)采用“盡最大努力交付”機制,請求數據包可能在路由跳轉過程中因鏈路擁塞、硬件故障或電磁干擾導致丟失、損壞或延遲,而客戶端無法直接知曉請求是被服務器正常處理,還是在傳輸途中發生異常。
TCP的確認并應答機制就很好的解決了這里問題: 客戶端在向服務端發送數據的時候,每次發送完一個數據,客戶端不會馬上接著發數據,而是會等待從服務端傳來的應答,當我們收到應答后,就可以確定數據成功到達了服務端
TCP通過肯定的確認應答(ACK)實現可靠的數據傳輸。當發送端將數據發出之后會等待對端的確認應答。如果有確認應答,說明數據已經成功到達對端。反之,則數據丟失的可能性很大。
這樣子可靠性就保證了 ,但是這樣子效率太低了。難道我說一句話,你都要先回一句:“我聽到了”,然后才說你想回應的話嗎?這個效率太低下了,正確的做法應該是將應答和想回復的消息一起發送回去,這種機制我們稱為捎帶應答。
當然上述方法我們仍面臨著許多問題,這就需要其他的一些機制來解決,后面我們會詳細介紹。
2.2.2 確認應答機制的優化
在進行網絡通信中,我們在考慮可靠性的同時,對效率也是有要求的,從上面部分我們可以看出,當通信一方發送一個請求后,一直在等待對方的應答回復,直至收到對方應答,才進行下一次發送,這也太扯了,所以在實際通信時是以下面的形式進行的:
這樣我們就將串行的應答方式,優化為了并行的方式。
2.3 超時重傳機制
在前面部分介紹的確認應答機制,依然存在著數據丟失問題當出現下面情況:
當主機A向主機B發送了一份數據,而在特定時間內沒有收到主機B的應答報文,這時主機A就會認為發送出去的數據丟失了,沒有正確到達主機B,主機A就會對這份數據重新補發,這種機制就叫超時重傳。
基于上述機制,新的問題隨之出現:若主機 A 發送的數據未丟失,卻在網絡中發生阻塞,待主機 A 補發請求并被主機 B 處理后,原數據才抵達主機 B;或者并非主機 A 發送的數據丟失,而是主機 B 回復的應答丟失,促使主機 A 補發數據。無論哪種情形,都會使主機 B 收到重復的請求。為了對上層應用提供可靠的傳輸,主機 B 顯然無法對重復請求逐一處理,這就要求 TCP 報文必須具備去重能力 。
為解決這一問題,需引入一種機制,既能夠識別已接收數據,又能判斷是否需要接收新數據。實際上,確認應答處理、重發控制以及重復數據控制等功能,均可通過序列號實現:TCP 會為發送數據的每個字節(8 位)按順序編號,接收端通過解析 TCP 首部中的序列號,結合數據長度,計算出“下一個期望接收的字節序號”,并將該序號作為確認應答(ACK)返回給發送端 。借助序列號與確認應答號的協同作用,TCP 得以實現數據的可靠傳輸,精準區分新數據與重復數據,避免重復處理,保障通信的有序性與準確性。
簡單而言就是將內核緩沖區視為數組,這樣我們的每個數據就天然的具備了自己的編號(數組下標),在發送TCP報文時依據特定算法,一次從緩沖區發送一部分數據,如1~1000,在此TCP報頭序號部分,填寫1000,當對方主機收到后就會在應答報文中,設置確認序號位1001,在協議中規定確認序號之前的數據已全部收到,即1001之前的數據全部收到,此后客戶端主機就可以依據序號來判斷,收到的TCP報文是否重復。
此方法也可以用來處理報文亂序問題:
比如先發送的報文由于路由原因導致后到達,而后發送的報文先到達等情況,此時就可以依據序號對TCP報文進行調整,其余有點后面介紹。
序號和確認序號
首先,客戶端待發送的數據,會先存入 TCP 的發送緩沖區(內核空間中的緩沖區)。由于 TCP 是面向字節流的協議,該緩沖區可抽象為一個 char
數組,數組里每個存儲單元對應一個字節,且自帶下標,這意味著緩沖區中每個字節天然具備唯一的順序編號 。我們寫入緩沖區的數據,會嚴格按照順序依次存儲,后續 TCP 協議正是基于這些字節的固有編號,通過序號機制實現數據的可靠傳輸 。
含義
序列號用于標識 TCP 報文段中第一個字節的數據序列,在 TCP 連接里,它代表報文段所攜數據的起始位置 。借助序列號,TCP 能保障數據傳輸時的順序性與完整性,讓接收方清晰知曉數據在字節流中的起始點位,為后續有序重組、校驗數據奠定基礎。
作用
TCP 連接建立階段,通信雙方會各自隨機選定初始序列號(ISN) 。后續傳輸報文段時,每個報文段的序號基于初始值,按所攜數據的字節數遞增。接收方利用序號,可對亂序抵達的報文段進行重組,確保數據順序正確、完整。一旦發現接收的報文段不連續,還能通過重傳機制,要求發送方補發缺失數據,以此保障可靠傳輸 。
對于確認序號,其值的含義是:接收方已成功接收確認序號對應數值之前的所有連續報文 。打個比方,若確認序號的值為 1001,意味著接收方不僅收到了序號為 1000 及更早的報文,且這些報文是連續無缺失的。從發送方視角理解,確認序號的值就等同于 自身下一次發送報文時,該報文序號應設置的數值 ,發送方后續可直接從這個序號開始,繼續傳輸新的數據段 。
含義
確認應答號(ACK Number)表示接收方期望接收的下一個報文段的起始序號,其本質是接收方向發送方反饋的“已確認接收數據的邊界”——即“我已完整收到該序號之前的所有連續數據,請從這個序號開始發送后續內容”。例如,若確認應答號為1001,則說明序號1000及之前的所有數據已被正確接收,發送方需從1001號字節起繼續傳輸。
作用
確認應答號是TCP實現可靠傳輸的核心機制,具體功能如下:
- 數據完整性校驗:接收方解析報文段后,將“當前報文序號+數據長度”作為確認應答號返回,使發送方明確知曉哪些數據已成功抵達。
- 重傳觸發機制:若發送方未在超時周期內收到對應確認應答號,或收到的確認應答號小于預期數據邊界,可判定數據丟失或亂序,從而觸發重傳邏輯。
- 有序傳輸控制:該機制與序列號協同工作,接收方通過確認應答號告知發送方“下一個期望接收的字節位置”,確保發送方按序發送數據,避免因亂序導致的傳輸錯誤。
以實例說明:發送方發送序號501、長度200字節的報文段,接收方正確接收后,會返回確認應答號701(501+200),明確指示“下一個期望接收的字節為701號”。
2.2 TCP協議的六個標志位
介紹這里就不得不提,TCP協議建立連接的過程了
首先我們要明確,服務器在給客戶端提供服務時,幾乎全部都是處與,一對多的形式:
在這中形式下,有的客戶端發送的TCP報文是給服務器申請建立連接,有的客戶端發送的是正在通信的報文,有點發送的是斷開連接的報文請求,那么我們的服務器該如何這些不同的請求呢,或者說該如何區分這寫不同的報文類型呢?
在TCP協議中的六個標志位,分別代表著不同的請求類型(報文類型)
以下是TCP協議六個標志位的功能說明表格:
標志位 | 英文全稱 | 功能描述 |
---|---|---|
URG | Urgent | 緊急指針有效標識,為1時表示需優先處理緊急數據,配合“緊急指針”字段使用 |
ACK | Acknowledgment | 確認號有效標識,為1時確認號字段生效,用于反饋已接收數據的狀態 |
PSH | Push | 提示接收端應用程序立即從TCP緩沖區讀取數據,無需等待緩沖區填滿 |
RST | Reset | 用于強制重置異常連接,攜帶該標志的報文為復位報文段,可拒絕非法請求或重建連接 |
SYN | Synchronize | 用于發起連接請求,攜帶該標志的為同步報文段,在三次握手首階段使用 |
FIN | Finish | 通知對方本端要關閉連接 |
ACK
ACK標志位用于指示報文中的確認號字段是否有效:僅當ACK=1時,確認號字段才具備實際意義。這一機制在TCP的確認回復流程中至關重要——當客戶端或服務端發送數據后,接收方需通過應答報文(或捎帶應答的報文)反饋接收狀態,此時必須將ACK標志位置1。
SYN
在TCP協議中,SYN標志位用于區分客戶端的請求類型——當客戶端發送的報文段攜帶SYN=1時,表明這是一個同步報文段,本質是客戶端向服務端發起的“連接建立請求”。作為服務端,正是通過檢測該標志位來判斷客戶端意圖:若收到SYN=1的報文,便知曉客戶端請求建立連接,此時會觸發TCP的三次握手流程(客戶端發送SYN→服務端回復SYN+ACK→客戶端發送ACK),從而在雙方之間建立可靠通信通道。
三次握手的具體實現,我會放在下篇文章中介紹
FIN
FIN標志位(Finish)用于標識斷開連接請求,當報文段攜帶FIN=1時,表明發送方已完成數據傳輸,請求終止TCP連接,該標記位是觸發四次揮手斷開流程的核心標識。
PSH
首先我們來回顧一下,Client在不斷發數據,Server在不斷接收數據同時在給Client發送應答,應答報文中包含了16位窗口大小的字段,其實就是在告訴Client自己接收緩沖區剩余空間的大小,以便于Client及時調整自己的發送速度,現在我們要引入一個場景:
當服務端因處理能力不足導致接收緩沖區滿溢時,客戶端發送的數據會在服務端緩沖區中排隊等待處理,進而導致客戶端無法及時收到確認應答。若客戶端需要實時了解服務端剩余接收空間以調整發送策略,此時發送普通探測報文可能因服務端緩沖區阻塞而無法及時處理。而將探測報文中的PSH標志位置1,可強制要求服務端接收該報文后立即將數據提交給應用層處理,繞過緩沖區排隊機制,使客戶端能快速獲取服務端的窗口狀態反饋,從而動態調整發送速率,避免因緩沖區擁塞導致的傳輸效率下降。
URG
URG標志位(緊急標記位)用于標識數據段中是否包含需優先處理的緊急數據:當URG=1時,表明數據段攜帶緊急數據,此時后續16位緊急指針字段生效。該機制適用于發送方需讓特定數據快速抵達接收方上層的場景——緊急指針表示緊急數據在數據段中的末尾偏移量(即從數據段首字節開始的偏移值),TCP協議規定,緊急數據的長度為“緊急指針值 - 數據段序號 + 1”。當接收方解析到URG=1時,會先讀取緊急指針指向的緊急數據(例如,若數據段序號為1000,緊急指針為1005,則緊急數據為1000~1004字節),再處理剩余數據。這類緊急數據被稱為“帶外數據”,可繞過常規緩沖區排隊機制優先交付給應用層,實現高優先級數據的快速傳輸。
RST
該標志位應該結合三次握手來理解,這里先簡單概述
在TCP協議中,RST標志位(復位標記位)用于處理異常連接狀態,當通信雙方對連接狀態的認知出現不一致時,感知到異常的一方會發送攜帶RST=1的復位報文段,強制終止當前連接并要求重新建立連接。具體場景如下:
-
三次握手或四次揮手的異常中斷:
若三次握手過程中某一方因網絡故障、資源不足等原因無法完成連接建立,或連接建立后某一方(如服務器)因斷電、重啟等突發情況導致連接狀態丟失,此時存活方(如客戶端)可能仍持有“連接有效”的狀態記錄,并繼續發送數據。例如服務器重啟后已忘記之前的連接,但客戶端仍向其發送報文,服務器會解析到異常的連接標識,隨即返回RST報文,明確告知“當前連接不存在,需重新發起三次握手”。 -
強制終止無效連接:
當接收方收到不屬于任何有效連接的報文段(如端口號錯誤、序列號錯位),或檢測到連接處于半開狀態(一方已關閉連接,另一方仍在發送數據),會通過RST標志位強制復位連接,避免資源浪費。
本質上,RST標志位是TCP處理連接異常的“緊急止損”機制,通過主動告知對方“連接狀態異常”,促使雙方重新同步狀態,確保后續通信基于有效連接進行,避免因狀態不一致導致的數據傳輸錯誤。
總結
本篇篇文章就介紹到這里,由于TCP協議較為復雜,有很多機制還沒有完全介紹,在后面一篇文章中,我會繼續對TCP協議的實現細節及各種機制進行補充。