TCPIP / 粘包和拆包的定义以及解决办法
一、粘包
1、定義
指發送方發送的若干數據包在接收方接收時粘成一團,從接收緩沖區看,后一包數據的頭緊接著前一包數據的尾。
2、產生的原因
(1)發送方的原因
TCP默認使用 Nagle 算法,而 Nagle 算法主要做如下兩件事情:
- 只有上一個分組得到確認,才發送下一個分組。
- 收集多個小分組,在一個確認到來時一起發送。
Nagle 算法造成了發送方可能存在粘包現象。
(2)接收端的原因
接收端接收到分組時,應用層并不會立即處理,接收端將接收到的分組放到接收緩存中,然后應用程序主動從接收緩存中讀取分組,當接收端接收分組的速度大于應用程序讀取分組的速度時,多個包就會被存至緩存。應用程序讀取時,就會讀到多個首尾相連在一起的包。
3、什么時候需要處理 TCP 粘包問題。
- 如果發送方的多個分組本來就是同一個數據的不同部分,比如一個很大的文件分成多個分組發送,這時不需要處理TCP粘包問題。
- 如果多個分組毫不相干,甚至是并聯關系,則一定要處理TCP粘包問題。
二、拆包
1、定義
發送方將一個數據包拆分成了多個數據包進行傳送。
2、產生的原因
- 要發送的數據大于 TCP 剩余緩沖區的大小。
- 要發送的數據大于 MSS 最大報文長度。
三、如何處理TCP粘包和TCP拆包問題
無論是TCP拆包還是TCP粘包本質問題都在于無法區分包的界限,可以采用以下三種方式來區分包的界限
四、代碼示栗
#pragma pack(1)struct XMNPkgHeader {// 報文的總長度(包頭 + 包體)。unsigned short pkglen;// 消息類型的代碼,用于區別不同的命令(消息)。unsigned short msgcode;// CRC32 校驗,用于防止接收到的數據和 client 發送的數據不符的問題。int crc32; };#pragma pack()之所以使用 pack(1) ,目的是讓包頭大小更緊湊,節約流量。 由于包頭的大小(headerlen)是固定的,通過 pkglen 就可以知道包體的大小(bodylen = pkglen - headerlen)。
在已知包頭和包體的長度的情況下,接受數據包的時候,首先可以接收?headerlen 大小的數據,如果接收的數據不夠,則下次接收包頭剩余的數據,直至包頭數據接收完畢。
包頭數據接收完畢之后,再接收 bodylen 大小的數據,如果接收的數據不足,則接收剩下的包體的數據,直至包體的數據接收完畢。
五、總結
TCP 之所以存在拆包和粘包問題,本質就是 TCP 是面向字節流的,而 UDP 是面向報文的!
六、源碼鏈接
https://github.com/xuchanglong/XMoon
?
(SAW:Game Over!)
總結
以上是生活随笔為你收集整理的TCPIP / 粘包和拆包的定义以及解决办法的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: TCP/IP / 如何进行堵塞控制?
- 下一篇: TCPIP / MTU 和 MSS 的区