在網路傳輸應用中,TCP/IP 協議與 Socket API 是主流選擇。TCP 提供高可靠性的面向連線服務,UDP 則提供高效率的無連線服務。實際工程中,重要資料傳輸常採用 TCP,但開發過程中常遇到「黏包」現象:發送端發送的多個資料包在接收端合併成一個包。本文深入分析黏包成因,並結合實驗提出高效解決對策。
TCP 是面向連線的傳輸層協議,雖非 ISO 標準,但已成事實標準。其目標是提供可靠的端到端連線,保證資料有序、無誤傳輸。為達此目標,TCP 採用序號、校驗和、確認重傳、流量控制等機制。這些可靠性保障雖降低傳輸效率,但對關鍵資料傳輸至關重要。
TCP 黏包是指發送端發送的多個資料包在接收端接收時黏成一包,接收緩衝區中後一包資料的包頭緊接著前一包的包尾。
對於無結構的連續流資料(如檔案傳輸),無須分包;但實際工程中傳輸的通常是帶結構資料,必須進行分包處理。
建立專門的預處理執行緒,負責將接收到的黏包資料流依協議格式拆分為獨立的完整包,再交給上層業務邏輯處理。經實驗驗證,此法高效可行,處理延遲極低。
發送/接收執行緒優先級設為 THREAD_PRIORITY_TIME_CRITICAL,預處理執行緒為 THREAD_PRIORITY_ABOVE_NORMAL,顯示執行緒為 THREAD_PRIORITY_NORMAL。
資料結構包含長度欄位 n。演算法將接收資料流強制轉換為預定結構,取出 n 並根據與目前資料流長度 m 的關係處理:
n < m:資料流含多包,從頭截取 n 位元組存入暫存區,剩餘資料迴圈處理。n = m:資料流恰為一完整包,直接存入暫存區。n > m:資料流不足一完整包,保留等待下一包合併處理。TCP_NODELAY 後無黏包。TCP 黏包確實存在,但可透過接收端預處理執行緒高效解決,處理耗時微乎其微,幾乎不影響應用程式正常運作。此架構適用於各類基於 TCP 的結構化資料傳輸系統。