單元 08 TCP 的狀態、視窗與壅塞
學習目標與問題
以單元 06、07 為先修。你應能追蹤三向握手、序號與 ACK,區分流量控制與壅塞控制,並分析吞吐量限制。遠端讀取太慢與路徑太擁擠是兩種不同問題。
8.1 握手與序號
假設客戶端初始序號 1000,伺服器 5000。SYN(seq1000)、SYN+ACK(seq5000,ack1001)、ACK(seq1001,ack5001) 建立雙向序號狀態。SYN 各佔一個序號;接著客戶端 100 bytes 的下一個待傳序號 1101。TCP 序號按 bytes 計量,並以模數規則處理回繞。
累積 ACK=N 表示 ACK 發出時希望取得的下一個 byte;不能理解成「第 N 個封包已到」。失序資料可能留在緩衝區,SACK 可描述額外區塊。ACK 到達不代表應用已消費,更不代表完成業務交易。

8.2 關閉與半關閉
兩個方向可各自用 FIN 結束傳送;FIN 佔一個序號。關閉可能四段完成,也可合併 ACK/FIN;「一定四次」不成立。半關閉允許一邊已不再傳送、仍接收另一邊資料。RST 代表中止,不能和正常 EOF 混為一談。
TIME_WAIT 協助處理重送的末尾封包及避免舊連線殘留干擾。大量連線時的資源問題需要量測與合理重用,不宜把關閉等待設定為零當成通用最佳化。
8.3 兩種視窗
rwnd 是接收端通告的可接收尺度,保護接收緩衝區;cwnd 是傳送端壅塞控制允許的在途尺度,保護網路。未確認 bytes 在簡化模型下受 min(rwnd,cwnd) 限制,實際可新增傳送量還要扣掉已在途資料,並考慮應用供給與其他機制。
例:已協商視窗縮放,rwnd=256 KiB、cwnd=64 KiB、RTT=50 ms、應用持續供給,視窗上界約 65536/0.05*8=10.49 Mb/s。即使把 rwnd 加到 1 MiB,cwnd 不變時仍不能單靠此提高上界。接收程式停讀可能令 rwnd 降到零;此時不是一定發生網路壅塞。
8.4 遺失恢復與 RTO
RTO 使用 RTT 估計與變動尺度;重傳後難以確定 ACK 對應哪次傳送,經典 Karn 規則避免用模糊樣本更新。逾時通常有退避。重複 ACK 與 SACK 等可協助較早偵測缺口,但重排也可能產生類似訊號。
經典 RFC 6298 更新模型:RTTVAR←(1-1/4)*RTTVAR+1/4*|舊SRTT-R|,再 SRTT←(1-1/8)*SRTT+1/8*R;RTO=SRTT+max(G,4×RTTVAR),G 是時鐘粒度;首次取樣設 SRTT=R、RTTVAR=R/2。RFC 6298 的一秒下限是 SHOULD,具體平臺可能採更短值。作業系統可能採不同允許的演進策略;本教材不以離線表格聲稱實測核心 RTO。
8.5 壅塞控制與公平性
經典 Reno 模型以 slow start 快速探索可用量,再以 congestion avoidance 較緩增加,偵測壅塞後降低視窗。slow start 雖名為「慢啟動」,在持續有資料可送、仍處慢啟動且 ACK 理想時,cwnd 約每個 RTT 倍增;增長仍受 ssthresh、ACK 時序與實作影響。CUBIC、BBR 等採不同模型,不能把一張鋸齒圖當成所有 TCP。
遺失型演算法與延遲/模型導向演算法可能對排隊和競爭有不同反應。公平性受 RTT、演算法、並行流數、瓶頸和排程影響;開更多連線可能取得更多資源,不代表協定更有效率。AQM/ECN 可提供壅塞訊號,深緩衝則可能造成 bufferbloat。
8.6 從資料到診斷
下載低速可以由小視窗、丟包、應用停頓、CPU、磁碟或瓶頸造成。看到重傳不能立即指控 ISP;看到低 CPU 也不能排除單執行緒瓶頸。先記錄工作負載、RTT、bytes、接收視窗和時間範圍,再針對假設增補資料。
實驗、習題與檢核
L05 驗證串流邊界,L06 驗證教學重傳狀態;選做 Wireshark 才討論真實 TCP 序號與視窗,擷取位置要記錄;Wireshark 預設常顯示相對序號,比對時要分清相對序號與原始序號。
- 上述握手後客戶端連續送 100 與 200 bytes,無遺失時累積 ACK 是多少?
- rwnd 很大、cwnd 很小時,增加接收緩衝可以保證增速嗎?
- 接收端零視窗與遺失造成逾時,所需調查有何不同?
- 為何不可只用下載平均速度判定演算法公平性?
檢核:能區分 bytes 序號、rwnd、cwnd、in-flight、goodput。來源:RFC 9293、RFC 5681、RFC 6298、RFC 7323、RFC 9438(CUBIC)。