文章目錄
- TCP協議理解
- 理論基礎
- TCP首部
- 結構圖示
- 字段逐項解析
- TCP是面向連接(Connection-Oriented)
- 面向連接的核心表現
- TCP 面向連接的核心特性
- TCP 與UDP對比
- TCP是一個可靠的(reliable)
- 序號與確認機制(Sequencing & Acknowledgment)
- 正常數據傳輸過程圖示
- 連接建立(三次握手)
- 數據傳輸
- 連接釋放(四次揮手)
- 補充說明
- 超時重傳(Retransmission Timeout, RTO)
- 正常傳輸(無重傳)
- 數據包丟失(F1 丟失)
- ACK 丟失(ACK1 丟失)
- ACK 延遲(ACK1 延遲)
- 數據包與 ACK 均丟失(F1 + ACK1 丟失)
- 接收方處理慢(ACK1 延遲)
- 流量控制(Flow Control)
- TCP 流量控制的工作原理
- 流量控制的實現方式
- 關鍵字段與術語
- 舉個例子來說明:
- 擁塞控制(Congestion Control)
- 擁塞控制的原理
- 擁塞控制的五種機制
- 擁塞控制的工作過程
- 擁塞控制算法的實際過程
- 擁塞控制的主要參數
- 擁塞控制算法示例:TCP Reno 和 TCP Tahoe
- 活動窗口+丟包重傳機制圖示
- 滑動窗口(Sliding Window)
- 丟包重傳機制
- 動態序列號與確認號
- 連接釋放
- 模擬丟包測試
- TCP是基于字節流(byte-TCPstream)的理解
- 五種典型場景說明:
- 關鍵結論:
- 全雙工的協議特性
- 補充知識
- 端口號
- 作用
- 端口號范圍
- TCP 常用端口
- Socket、五元組與TCP/IP協議的關系
- Socket(套字節) 是網絡編程的基石
- 五元組是連接的唯一標識
- 分層圖示:TCP/IP協議棧與Socket的位置
- TCP連接建立的五元組交互(三次握手)
TCP協議理解
TCP是一個可靠的(reliable) 、面向連接的(connection-oriented)、基于字節流(byte-TCPstream)、全雙工的(ful1-duplex) 協議。可靠傳輸是通過一系列復雜的機制實現的,確保數據在網絡中有序、無丟失、無重復地到達目標端。
理論基礎
TCP首部
結構圖示
字段逐項解析
- 源端口 & 目的端口(各16位)
- 作用:標識發送方和接收方的應用程序。
- 源端口:客戶端隨機分配(動態端口,范圍49152~65535)。
- 目的端口:服務端固定端口(如HTTP:80、SSH:22)。
- 作用:標識發送方和接收方的應用程序。
- 序列號(32位)
- 作用:標識發送的數據字節流的順序號,解決亂序問題。
- 初始序列號(ISN):在三次握手時隨機生成,避免歷史報文沖突。
- 規則:每發送1字節數據,序列號+1。
- 作用:標識發送的數據字節流的順序號,解決亂序問題。
- 確認號(32位)
- 作用:期望收到的下一個字節的序列號,實現可靠傳輸。
- 規則:確認號 = 對方序列號 + 已接收數據長度 + 1(若含SYN/FIN標志,+1)。
- 數據偏移(4位)
- 作用:指示TCP頭部長度(以4字節為單位)。
- 計算:頭部長度 = 數據偏移值 × 4(最小5,即20字節;最大15,即60字節)。
- 作用:指示TCP頭部長度(以4字節為單位)。
- 保留字段(6位)
- 作用:保留給未來使用,必須置0。
- 控制標志(6位,每1位表示一個狀態)
標志位 | 名稱 | 作用 |
---|---|---|
URG | 緊急 | 為1時,啟用緊急指針(需配合緊急指針字段) |
ACK | 確認 | 為1時,確認號有效(建立連接后所有報文ACK=1) |
PSH | 推送 | 為1時,要求接收方立即將數據交給應用層(如Telnet輸入) |
RST | 重置 | 為1時,強制斷開連接(用于異常恢復) |
SYN | 同步 | 為1時,表示發起連接請求(三次握手階段使用) |
FIN | 結束 | 為1時,表示發送方數據發送完畢(四次揮手階段使用) |
-
常見組合:
- SYN=1, ACK=0:第一次握手(連接請求)
- SYN=1, ACK=1:第二次握手(連接確認)
- SYN=0, ACK=1:第三次握手 (建立連接)
- 傳輸數據。。。。
- FIN=1, ACK=1:四次揮手 (關閉連接請求)
-
窗口大小(16位)
- 作用:接收方的可用緩沖區大小(流量控制關鍵字段)。
- 單位:字節(最大65535字節,若啟用窗口縮放選項可擴展)。
- 動態調整:通過滑動窗口協議控制發送速率。
- 作用:接收方的可用緩沖區大小(流量控制關鍵字段)。
-
校驗和(16位)
- 作用:檢測頭部和數據的傳輸錯誤(覆蓋偽頭部+TCP頭部+數據)。
- 算法:反碼求和再取反。
- 偽頭部字段:包含源/目的IP、協議類型等,增強校驗強度。
- 作用:檢測頭部和數據的傳輸錯誤(覆蓋偽頭部+TCP頭部+數據)。
-
緊急指針(16位)
- 作用:當URG=1時,指示緊急數據的末尾偏移量(相對于序列號)。
- 應用場景:中斷遠程命令(如Ctrl+C)。
-
選項字段(可選)
- 作用:擴展TCP功能,常見選項:
類型 長度 功能 MSS(最大報文段) 4字節 協商雙方能接收的最大數據段長度 窗口縮放 3字節 將窗口大小擴展至1GB(左移0~14位) SACK(選擇性確認) 可變 支持只重傳丟失的報文段 時間戳 10字節 計算RTT(往返時間)和防止序號回繞
TCP是面向連接(Connection-Oriented)
面向連接的核心表現
-
三次握手(建立連接)
-
SYN:A 發起連接請求,攜帶初始序列號(seq=100)。
-
SYN-ACK:B 確認 A 的序列號(ack=101),并發送自己的序列號(seq=300)。
-
ACK:A 確認 B 的序列號(ack=301),連接建立。
-
-
數據傳輸(可靠傳輸)
-
PSH:A 發送數據 “hello”(占 5 字節,seq=101),B 必須回復 ACK(ack=106)。
-
應用層響應:B 發送 “world”(可選,由應用協議決定)。
-
-
四次揮手(釋放連接)
-
FIN:A 發起關閉請求。
-
ACK:B 確認收到,可能繼續發送剩余數據。
-
FIN:B 發起關閉請求。
-
ACK:A 確認,連接完全關閉。
-
TCP 面向連接的核心特性
特性 | 說明 | 圖示對應部分 |
---|---|---|
預先建立連接 | 通信前需通過三次握手協商參數(序列號、窗口大小等)。 | 三次握手階段 |
可靠傳輸 | 每個數據包必須被確認(ACK),超時重傳,保證數據不丟失、不重復、按序到達。 | 數據傳輸階段的 ACK 機制 |
狀態維護 | 兩端維護連接狀態(如 ESTABLISHED、TIME_WAIT)。 | 整個生命周期 |
有序釋放連接 | 通過四次揮手安全關閉連接,避免數據丟失。 | 四次揮手階段 |
TCP 與UDP對比
對比項 | TCP | UDP |
---|---|---|
全稱 | 傳輸控制協議(Transmission Control Protocol) | 用戶數據報協議(User Datagram Protocol) |
連接性 | 面向連接(需三次握手建立連接) | 無連接(直接發送數據) |
可靠性 | 可靠傳輸(確認、重傳、排序機制) | 不可靠傳輸(無確認、重傳機制) |
數據順序 | 保證數據按序到達 | 不保證數據順序 |
流量控制 | 支持(滑動窗口機制) | 不支持 |
擁塞控制 | 支持(動態調整發送速率) | 不支持 |
傳輸速度 | 較慢(需額外控制機制) | 較快(無額外控制開銷) |
頭部大小 | 較大(20-60 字節,包含更多控制信息) | 較小(8 字節,固定頭部) |
適用場景 | 對可靠性要求高的場景(如網頁、文件傳輸) | 對實時性要求高的場景(如視頻流、在線游戲) |
數據邊界 | 無明確邊界(基于字節流) | 有明確邊界(保留數據報邊界) |
協議復雜度 | 復雜 | 簡單 |
典型應用 | HTTP、FTP、SMTP、SSH | DNS、VoIP、直播、在線游戲 |
UDP數據傳輸圖示
TCP是一個可靠的(reliable)
TCP 通過以下 4 種關鍵技術保證可靠性:
序號與確認機制(Sequencing & Acknowledgment)
正常數據傳輸過程圖示
注意:上圖中大寫的ACK是標志位,小寫ack是回應對方的確認號
-
用netcat 和 wireshare 模擬抓包TCP過程
連接建立(三次握手)
- SYN: 同步序列號,初始化連接。
- ACK: 確認對方的序列號。
- 最終雙方進入 ESTABLISHED 狀態。
- 三次握手示意圖
數據傳輸
- 每次發送數據時:
- seq 為當前數據包的起始序列號。
- ack 為期望收到的下一個字節的序列號(即對方seq + 數據長度)。
- 示例中傳輸了三條數據:“Hello” → “Hi” → “Bye”。
連接釋放(四次揮手)
- FIN: 終止連接請求。
- 客戶端和服務器各自發送 FIN 并確認對方的 FIN,最終進入 CLOSED 狀態。
- 客戶端在 TIME_WAIT 狀態等待 2MSL(確保最后一個 ACK 到達服務器)。
- 狀態說明表格:
狀態 | 所屬方 | 含義 |
---|---|---|
FIN-WAIT-1 | 客戶端 | 發送FIN后等待服務器ACK確認 |
CLOSE-WAIT | 服務器 | 收到FIN后進入半關閉狀態,等待應用層處理剩余數據 |
FIN-WAIT-2 | 客戶端 | 收到服務器ACK后,等待服務器發送FIN |
LAST-ACK | 服務器 | 發送FIN后等待客戶端最終ACK確認 |
TIME-WAIT | 客戶端 | 發送最后一個ACK后等待2MSL(防止ACK丟失,確保服務器能正常關閉) |
CLOSED | 雙方 | 連接完全關閉 |
-
什么是
MSL
?
MSL(Maximum Segment Lifetime,報文最大生存時間)是 TCP 報文在網絡中的最長存活時間,超過該時間未被接收的報文會被丟棄。2MSL 是 TCP 連接在 TIME-WAIT 狀態的等待時長,即 兩倍的 MSL。- 在 Linux 系統中,MSL 默認為 60秒,因此 TIME-WAIT 狀態持續 120秒(2MSL)。
- Windows 系統中 MSL 通常為 2分鐘(TIME-WAIT 為 4分鐘)。
-
為什么需要
TIME-WAIT
?-
確保最后一個ACK到達服務器,若丟失,服務器會重傳FIN,客戶端可重新響應ACK。
-
防止舊連接的延遲數據包干擾新連接(通過2MSL等待舊數據包失效)。
-
wireshare抓包情況
-
在windows下cmd中用
netstat
工具查看連接狀態
-
補充說明
-
序列號(seq)和確認號(ack)
- 每次傳輸數據后,seq 和 ack 會動態變化,遵循規則:
- ack = 對方上一次的seq + 數據長度。
-
為什么需要三次握手四次揮手?
-
三次握手的原因
-
確認雙向通信能力
通過客戶端發送SYN、服務端回復SYN+ACK、客戶端再回復ACK的三次交互,驗證雙方的發送和接收功能正常。 -
同步初始序列號
交換序列號(seq)和確認號(ack),為后續數據傳輸提供有序性保障。 -
防止歷史連接干擾
若網絡延遲導致舊SYN報文到達,服務端會要求客戶端確認,避免無效連接占用資源。 -
協商窗口參數
在握手過程中同步TCP窗口大小等配置,優化數據傳輸效率。
-
-
四次揮手的原因
-
全雙工連接的獨立關閉
TCP連接是雙向的,客戶端和服務端需分別發送FIN和ACK來關閉各自的通道。- 第一次揮手:主動方發送FIN,表示不再發送數據。
- 第二次揮手:被動方回復ACK,確認收到關閉請求。
- 第三次揮手:被動方發送FIN,表示自身數據已發送完畢。
- 第四次揮手:主動方回復ACK,最終確認連接釋放。
-
確保數據完整性
四次揮手允許被動方在ACK后繼續發送剩余數據,避免數據丟失。 -
處理延遲報文
通過TIME_WAIT狀態等待可能滯留在網絡中的報文,防止新連接收到舊數據。
-
-
為什么不簡化握手或揮手?
-
兩次握手不足
無法驗證客戶端的接收能力,且易受歷史SYN報文干擾。 -
三次揮手不可行
被動方的ACK和FIN通常無法合并發送,因為數據可能未傳輸完成。
-
通過這種設計,TCP在不可靠的IP層上實現了可靠的端到端通信。
-
-
理解Wireshare抓包中的序列號(seq)和確認號(ack)都是wireshare處理后的相對序號/確認號
-
實際傳輸值
-
是32位無符號整數,范圍0-4294967295
-
表示該報文段中第一個數據字節的編號
-
初始序列號(ISN)是隨機生成的(安全考慮)
-
-
Wireshark顯示方式
-
相對序號:默認顯示相對于初始序列號的偏移量
-
第一個包的Seq顯示為0(實際可能是任意ISN值)
-
后續包顯示相對于ISN的增量
-
絕對序號:可通過右鍵菜單切換顯示實際值
-
-
超時重傳(Retransmission Timeout, RTO)
TCP 超時重傳場景分析
正常傳輸(無重傳)
-
流程:
F1 (Seq=1) → ACK1 → F2 (Seq=2)
-
說明:
數據包和 ACK 均正常到達,無需重傳。
數據包丟失(F1 丟失)
-
流程:
F1 (丟失) → [超時] → F1 (重傳) → ACK1
-
原因:
網絡擁塞、鏈路錯誤導致數據包丟失。 -
解決方案:
- 啟用 快速重傳(Fast Retransmit)(需 SACK 支持)
- 優化網絡路徑(如切換路由、檢查 QoS)
ACK 丟失(ACK1 丟失)
-
流程:
F1 (Seq=1) → ACK1 (丟失) → [超時] → F1 (重傳) → ACK1 (重發)
-
原因:
接收方的 ACK 確認包丟失,發送方誤判數據未到達。 -
解決方案:
- 動態調整 RTO(重傳超時時間) 減少誤判
- 使用 SACK(選擇性確認) 避免重復傳輸已接收數據
ACK 延遲(ACK1 延遲)
-
流程:
F1 (Seq=1) → ACK1 (延遲) → [超時] → F1 (重傳) → ACK1 (重發)
-
原因:
ACK 因網絡抖動延遲到達,觸發不必要的重傳。 -
解決方案:
- 優化 RTT(往返時間) 計算算法(如 Linux 默認的 RFC6298)
- 啟用 時間戳選項(TCP Timestamps) 更精確估算延遲
數據包與 ACK 均丟失(F1 + ACK1 丟失)
-
流程:
F1 (丟失) + ACK1 (丟失) → [超時] → F1 (重傳) → ACK1
-
原因:
雙向通信均失敗,可能是網絡分區或嚴重擁塞。 -
解決方案:
- 增加 最大重傳次數(如 Linux 的 tcp_retries2)
- 監控網絡狀態(如 ICMP 探測、BGP 路由檢查)
接收方處理慢(ACK1 延遲)
-
流程:
F1 (Seq=1) → [處理延遲] → [超時] → F1 (重傳) → ACK1 (重發)
-
原因:
接收方應用層處理緩慢(如緩沖區滿、高負載)。 -
解決方案:
- 調整接收方 TCP 接收窗口(RWND)
- 優化應用代碼(如異步 I/O、批量處理)
流量控制(Flow Control)
TCP 流量控制是確保在網絡通信中發送方不會過度傳輸數據以至于接收方無法及時處理的機制。流量控制的核心目的是防止接收方的緩沖區溢出,確保數據傳輸的可靠性和穩定性。
TCP 流量控制的工作原理
在 TCP 連接中,流量控制依賴于 接收窗口(Receive Window) 來管理數據傳輸。接收窗口是接收方通知發送方當前可用的緩沖區空間大小,發送方根據這個窗口來決定可以發送多少數據。
以下是 TCP 流量控制的主要概念:
-
接收窗口(Window Size):
- 每次發送方發送數據時,它會檢查接收方的接收窗口大小。接收窗口大小由接收方在每個 TCP 數據包的頭部通知給發送方。
- 接收窗口的大小決定了在不等待確認的情況下,發送方最多可以發送的字節數。接收方通過不斷地更新窗口大小來通知發送方當前可接受的緩沖區空間。
-
滑動窗口(Sliding Window):
- TCP 使用滑動窗口機制來進行流量控制,發送方通過滑動窗口來控制數據的流量。
- 當接收方確認已收到數據時,窗口向前滑動,釋放出空間,從而允許發送方發送更多的數據。
- 這個窗口并不是固定大小的,它會隨著接收方處理數據的速度和窗口大小的更新而動態調整。
-
流量控制過程:
- 發送方:發送方發送數據到接收方,并在每個數據包中包含當前的接收窗口大小。
- 接收方:接收方在收到數據后,會根據其緩沖區的空閑空間更新接收窗口大小。
- 滑動窗口更新:當接收方成功處理某些數據并釋放緩沖區空間時,接收方會通過窗口更新通知發送方,發送方則可以繼續發送數據。
流量控制的實現方式
- 接收方窗口大小的動態調整:
- 在 TCP 握手期間,接收方會告知發送方自己的接收窗口的大小。
- 接收方根據自己的緩沖區的使用情況來調整接收窗口。如果接收方的緩沖區已經滿了,接收窗口會變小或甚至為零,這會告訴發送方暫時停止發送數據。
- 例如,當接收方的緩沖區空間快用完時,接收窗口會減少,發送方的發送速率也會受到影響。
- 流量控制與擁塞控制:
- 流量控制與擁塞控制是 TCP 中的兩個不同機制。流量控制關注的是如何控制數據傳輸速率以避免接收方緩沖區溢出,而擁塞控制則是為了避免網絡中的過度擁塞。
- 流量控制是基于接收方的緩沖區情況來進行調節,而擁塞控制則是基于整個網絡的負載情況進行調節。
關鍵字段與術語
-
rwnd (Receive Window):
- rwnd 是接收窗口的大小,表示接收方的緩沖區剩余的可用空間。這個值會通過 TCP 頭部的字段傳遞給發送方。
-
窗口大小字段:
- 在 TCP 頭部,有一個字段專門用于表示接收窗口大小,它是一個 16 位的數值,表示當前接收方能接收的字節數。
舉個例子來說明:
假設發送方正在發送大量的數據,而接收方的接收窗口初始大小為 10,000 字節。發送方會按照這個窗口大小發送數據。
- 發送方發送了 10,000 字節的數據。
- 接收方處理了其中的一部分數據并釋放了 4,000 字節的緩沖區空間。
- 接收方通過更新窗口大小,告知發送方新的接收窗口大小為 4,000 字節。
- 發送方在接收到這個更新的窗口大小后,調整自己的發送速率,并根據接收窗口的大小來決定可以發送多少數據。
- 如果接收方的緩沖區空間已滿,接收窗口大小會變為零,通知發送方停止發送數據,直到接收方處理了足夠的數據,窗口大小才會重新增大。
擁塞控制(Congestion Control)
擁塞控制(Congestion Control)是 TCP 協議中一個非常重要的機制,旨在防止網絡中的數據包過度積壓或擁堵,從而影響數據的傳輸效率與可靠性。它的主要目標是確保數據傳輸在網絡的可承載范圍內進行,避免因網絡負載過高導致的丟包、延遲和流量不穩定。
擁塞控制的原理
擁塞控制的核心思想是根據網絡的實際狀況(如帶寬、延遲、丟包率等)動態調整發送方的數據發送速率,以防止網絡擁塞。當網絡出現擁塞時,TCP 會自動減慢數據發送速率;當網絡空閑時,TCP 會逐步增加發送速率。
擁塞控制的五種機制
- 慢啟動(Slow Start)
- 擁塞避免(Congestion Avoidance)
- 快速重傳(Fast Retransmit)
- 快速恢復(Fast Recovery)
- 擁塞窗口(Congestion Window, cwnd)
擁塞控制的工作過程
-
慢啟動階段(Slow Start):
- 初始時,TCP 連接的擁塞窗口(cwnd)被設置為一個小的值(通常為 1 或 2 個最大報文段長度(MSS))。
- 每收到一個確認(ACK)包,發送方就會將擁塞窗口大小增加一個 MSS,即窗口大小以指數級增長。
- 該階段持續到擁塞窗口大小達到一個閾值(慢啟動閾值,ssthresh),此時轉入擁塞避免階段。
-
擁塞避免階段(Congestion Avoidance):
- 當擁塞窗口達到慢啟動閾值后,TCP 會進入擁塞避免階段。在這個階段,窗口大小的增長速度會減緩,從指數增長轉為線性增長。
- 每收到一個確認包,擁塞窗口(cwnd)會增加一個 MSS 除以當前的擁塞窗口大小。
- 這一階段的目標是平穩地增加發送速率,避免因為過快的速率增加而導致網絡擁塞。
-
丟包檢測與快速重傳(Fast Retransmit):
- 如果發送方連續收到三個相同的確認號(即出現三次重復確認),說明某個數據包丟失了。
- TCP 會立即重傳丟失的數據包,而不需要等待超時。
- 快速重傳的機制能夠減少丟包后等待超時的時間,加速數據的恢復過程。
-
快速恢復階段(Fast Recovery):
- 在丟包發生并進行快速重傳后,TCP 會進入快速恢復階段。在該階段,擁塞窗口會進行適當的調整,通常是將擁塞窗口減半(cwnd = cwnd / 2),而不是直接回到慢啟動階段。
- 快速恢復階段的目的是盡量恢復丟包后的網絡狀況,并避免過度回退。
-
擁塞窗口的調整:
- 在慢啟動和擁塞避免階段,TCP 會根據網絡的反饋動態調整擁塞窗口大小。
- 當發生擁塞時(如丟包發生),TCP 會減小擁塞窗口的大小,并且通過逐步增加(慢啟動)或線性增加(擁塞避免)來找到適合的發送速率。
擁塞控制算法的實際過程
-
慢啟動:
- 初始時,cwnd 通常設為 1 MSS。
- 每當收到一個確認包(ACK),cwnd 就加 1 MSS,窗口大小呈指數增長。
- 當 cwnd 達到慢啟動閾值(ssthresh)時,進入擁塞避免階段。
-
擁塞避免:
- cwnd 達到 ssthresh 后,進入線性增長階段。每收到一個確認包,cwnd 增加 1 MSS / cwnd。
- 這種增長是線性的,能夠平穩地增加發送速率,防止網絡過載。
-
快速重傳與快速恢復:
- 在接收到 3 次重復確認時,認為發生了丟包。
- 快速重傳會立即重發丟失的包,而不是等待超時。
- 快速恢復會將 cwnd 減少一半,然后繼續進行擁塞避免。
擁塞控制的主要參數
-
擁塞窗口(Congestion Window,cwnd):
- 擁塞窗口是發送方控制發送速率的關鍵參數,它定義了在網絡中可以未確認的數據的最大字節數。
- 擁塞窗口的大小會根據網絡的擁塞狀況動態調整。較大的 cwnd 可以提高數據傳輸速率,較小的 cwnd 會減少發送速率,從而緩解擁塞。
-
慢啟動閾值(Slow Start Threshold,ssthresh):
- ssthresh 是決定 TCP 何時從慢啟動階段轉到擁塞避免階段的閾值。
- 當發生擁塞(如丟包)時,ssthresh 會減小,以限制數據的快速增長。
-
超時重傳:
- 當發送方未收到某個數據包的確認(ACK)時,它會觸發超時重傳機制。這通常會導致擁塞窗口被重置為一個較小的值,并重新開始慢啟動。
擁塞控制算法示例:TCP Reno 和 TCP Tahoe
- TCP Tahoe:使用慢啟動、擁塞避免和超時重傳機制。在發生丟包時,cwnd 會被重置為 1 MSS,然后重新進入慢啟動階段。
- TCP Reno:在 TCP Tahoe 的基礎上增加了快速重傳和快速恢復機制。當檢測到丟包時,cwnd 會減小一半,并進入快速恢復階段,而不是回到慢啟動。
活動窗口+丟包重傳機制圖示
滑動窗口(Sliding Window)
- 窗口大小 Win=3 表示客戶端無需等待ACK即可連續發送3個數據包(P1、P2、P3)。
- 服務器通過 ack 動態調整窗口(示例中因丟包暫停滑動)。
丟包重傳機制
- 快速重傳:服務器連續3次返回相同的 ack=2(表示P2丟失),客戶端立即重傳P2。
- 超時重傳:P4未收到ACK,客戶端等待超時后重傳。
動態序列號與確認號
- 數據包長度影響 ack 值(如 data=“P1” 長度為1,則下一個 ack=2)。
- 重傳包的 seq 不變(如P2重傳時仍為 seq=2)。
連接釋放
- 客戶端和服務器各自發送 FIN 并確認,最終客戶端進入 TIME_WAIT 狀態(等待2MSL)。
模擬丟包測試
- 為了更精確地模擬滑動窗口和重傳機制,使用
iperf
和netem
等工具制造條件- netem 是Linux內核中的一個網絡模擬模塊,它允許你模擬網絡延遲、丟包、重復和亂序等條件,使用
tc
(Traffic Control)工具來配置 netem iperf
是一個網絡性能測試工具(需要額外安裝yum install -y iperf
),它可以用來測量TCP和UDP帶寬性能。可以使用iperf
來模擬不同的帶寬和延遲條件,從而觀察TCP連接在這些條件下的行為
- netem 是Linux內核中的一個網絡模擬模塊,它允許你模擬網絡延遲、丟包、重復和亂序等條件,使用
- 服務器端 使用
netem(tc)
模擬網絡延遲和丟包
# 在服務端上設置50%丟包率
tc qdisc add dev eth0 root netem loss 50%# 啟動iperf服務器
iperf -s
- 在另一臺機器上運行客戶端測試
# 設置非常小的窗口大小
iperf -c <server_ip> -w 1k
- 測試完成后移除服務端丟包規則
tc qdisc del dev eth0 root
TCP是基于字節流(byte-TCPstream)的理解
一種字節流協議,流的含義是沒有固定的報文邊界
五種典型場景說明:
-
完整發送
-
發送方三次寫入(200B+300B+500B)→ 接收方一次讀取1000B
-
典型場景:Nagle算法關閉時的小數據快速發送
-
-
拆分發送
-
原始數據被拆分為400B+600B兩個TCP段
-
原因:MTU限制或擁塞控制導致分片
-
-
部分粘包
-
前兩次寫入(200B+300B)合并發送,第三次單獨發送
-
接收方讀取時出現500B+500B的分界
-
-
數據混合
-
當前應用數據與其他應用數據混合傳輸
-
需要應用層協議自行區分(如HTTP頭部的Content-Length)
-
-
拆分成小包
-
大數據塊被拆分為多個小包傳輸
-
常見于慢啟動階段或高延遲網絡
-
關鍵結論:
-
TCP的字節流特性導致以下不確定性:
-
寫入/讀取次數不對應
-
數據塊大小不對應
-
報文邊界不保留
-
-
必須通過應用層協議解決:
-
最常用方案:長度前綴(如HTTP/WebSocket)
-
簡單方案:分隔符(如Redis協議)
-
特殊場景:定長(如視頻流分片)
-
全雙工的協議特性
補充知識
端口號
端口號是網絡通信中用于區分不同應用程序或服務的邏輯標識,與IP地址結合形成套接字(Socket),實現端到端的精準通信。
作用
-
定位應用層服務:同一臺主機上可能有多個網絡應用(如Web服務器、FTP服務器),端口號幫助區分這些服務。
-
多路復用/解復用:通過端口號,傳輸層(TCP/UDP)將數據準確交付給目標應用程序。
端口號范圍
-
16位無符號整數:范圍 0~65535(2^16)
-
分類
類型 | 范圍 | 說明 |
---|---|---|
知名端口 | 0~1023 | 分配給系統服務(如HTTP:80) |
注冊端口 | 1024~49151 | 用戶程序可注冊的端口(如MySQL:3306) |
動態/私有端口 | 49152~65535 | 客戶端臨時使用的端口(操作系統隨機分配) |
TCP 常用端口
端口號 | 協議/服務 | 說明 |
---|---|---|
20/21 | FTP | 文件傳輸(數據/控制連接) |
22 | SSH | 安全遠程登錄 |
80 | HTTP | 網頁訪問 |
443 | HTTPS | 加密網頁訪問 |
3306 | MySQL | 數據庫服務 |
3389 | RDP | 遠程桌面協議 |
Socket、五元組與TCP/IP協議的關系
Socket(套字節) 是網絡編程的基石
- 作用:Socket 是操作系統提供給應用程序的 編程接口(API),開發者通過它實現網絡通信(如建立連接、發送數據)
- Socket 由以下幾個部分組成:
- 協議族(如:IPv4 或 IPv6)
- 傳輸協議(如:TCP 或 UDP)
- 端口號
- IP 地址
在編程中,Socket 通常是通過操作系統提供的 API 來創建的,用于實現網絡連接。Socket 使得應用程序可以通過指定端口、IP 地址和協議類型來進行通信。它是實現網絡通信的抽象。
五元組是連接的唯一標識
組成:協議 + 源IP + 源端口 + 目標IP + 目標端口。
元素 | 說明 | 示例 |
---|---|---|
傳輸層協議 | 指明使用 TCP 還是 UDP | TCP、UDP |
源IP地址 | 發起通信的主機 IP 地址 | 192.168.1.100 |
源端口 | 發起通信的應用程序端口(臨時端口,通常由操作系統動態分配) | 54322 |
目的IP地址 | 目標主機的 IP 地址 | 10.0.0.5 |
目的端口 | 目標應用程序的端口(知名端口或注冊端口,如 HTTP-80、SSH-22) | 80 |
舉例說明:
- 操作系統通過五元組區分不同的網絡連接。例如,同一臺主機上的多個瀏覽器標簽訪問同一網站時,每個連接的五元組中的 源端口 不同。
連接1: [TCP, 192.168.1.100:54322 → 10.0.0.5:80]
連接2: [TCP, 192.168.1.100:54323 → 10.0.0.5:80]
分層圖示:TCP/IP協議棧與Socket的位置
+-----------------------+
| Application | ← 應用程序(HTTP/FTP/SSH)
+-----------------------+
| Socket | ← 編程接口(API)
+-----------------------+
| Transport (TCP/UDP) | ← 五元組在此層生效
+-----------------------+
| Network (IP/ICMP) |
+-----------------------+
| Link (Ethernet) |
+-----------------------+
- Socket 是應用層與傳輸層之間的橋梁,開發者通過它調用TCP/UDP功能。
- 五元組 在傳輸層(TCP/UDP)中唯一標識一個連接。
TCP連接建立的五元組交互(三次握手)
- 握手過程中,雙方Socket根據五元組確認連接歸屬。