Microsoft TCP 協議棧在處理小數據包時,三大機制交織影響性能:
send 的小數據合併,待收到前一包 ACK 後統一發送(超過 MTU 1460 字節立即發送)send 只是拷貝到內核緩衝區,非實際發送;SO_SNDBUF=0 可禁用客戶端發 10000 條記錄 (20~100 字節) 到服務端存庫。客戶端設置 SO_SNDBUF=0 禁用緩衝,**未關閉 Nagle**。
傳 976KB 耗時 **半個多小時**,吞吐 ~5 條/秒。
send → 內核緩衝區 (已禁用,直接交 TCP)SO_SNDBUF=0),積累數據超過 MTU 直接發送,繞過 Nagle 等待send 發 80 條記錄 (~8KB),頭部標記條數TCP_NODELAY 禁用 Nagle (需配合組包,否則產生大量微小包)股票報價:命令通道發請求,數據通道收報價。雙方均未設置 TCP_NODELAY。
每秒僅 5 條報價。
TCP_NODELAY| 建議 | 理由 |
|---|---|
| 應用層組包,單次 send 發 4KB~8KB | 減少系統調用、繞過 Nagle 等待、提高帶寬利用率 |
| 避免單向流連續小包 | 觸發延遲 ACK + Nagle 雙重延遲 |
| 默認保留 8KB SO_SNDBUF | 內核緩衝吸收突發,平滑發送 |
| 不設 SO_SNDBUF=0 除非極低延遲場景 | 禁用緩衝導致每包進入 Nagle 等待 |
| 請求-響應用單連接 | ACK 搭便車,消除延遲 ACK 罰時 |
| 不可靠傳輸改用 UDP | 避開 TCP 複雜流控 |
// 禁用 Nagle
int on = 1;
setsockopt(sock, IPPROTO_TCP, TCP_NODELAY, &on, sizeof(on));
// 設置發送緩衝區
int bufsize = 64*1024; // 64KB
setsockopt(sock, SOL_SOCKET, SO_SNDBUF, &bufsize, sizeof(bufsize));
TCP 小包傳輸效率問題本質是 **Nagle 算法與延遲 ACK 的負向共振**。理解三大機制交互,應用層組包 + 合理 socket 選項,能將吞吐提升 **數十倍甚至上百倍**。這是網絡編程從「能跑通」到「跑得快」的關鍵分水嶺。