TCP協議是可靠的,數據包一定會到達(99.9%的情況下),而且是按順序到達。
TCP是“流”協議,所謂“流”協議,就是沒有界限,沒有分割的一串數據。TCP會根據緩沖區實際情況進行划分,一個完整的包可能會拆分成多個包進行發送,也有可能把多個小包封裝成一個大的數據包發送,這就是TCP粘包/拆包。
發生原因
- 應用程序寫入的數據大於套接字緩沖區大小,這將會發生拆包。
- 應用程序寫入數據小於套接字緩沖區大小,網卡將應用多次寫入的數據發送到網絡上,這將會發生粘包。
- 接收方法不及時讀取套接字緩沖區數據,這將發生粘包。
解決方案
無論拆包還是粘包本質問題都是無法區分包界限,解決包界限的問題主要有以下幾種方式:
- 消息數據的定長,比如定長100字節,不足補空格,接收方收到后解析100字節數據即為完整數據。但這樣的做的缺點是浪費了部分存儲空間和帶寬。
- 消息數據使用特定分割符區分界限,比如使用換號符號做分割。
- 把消息數據分成消息頭和消息體,消息頭帶消息的長度,接收方收到后根據消息頭中的長度解析數據。
在實際開發中很多網絡框架對TCP拆包粘包問題的解決做了很多支持,比如netty中LineBasedFrameDecoder解析器就是利用換號符號做分割。
參考文檔
【1】淺談TCP拆包粘包問題
【2】TCP粘包/拆包
【3】TCP粘包,拆包及解決方法