Socket解決粘包問題1,socket解決粘包
粘包是指發送端發送的包速度過快,到接收端那邊多包並成一個包的現象,比如發送端連續10次發送1個字符'a',因為發送的速度很快,接收端可能一次就收到了10個字符'aaaaaaaaaa',這就是接收端的粘包。
可能我們在平時練習時沒覺的粘包有什麼危害,或者通過把發送端發送的速率調慢來解決粘包,但在實時通信中,發送端常常是單片機或者其他系統的信息采集機,它們的發送速率是無法控制的,如果不解決接收端的粘包問題,我們無法獲得正常的信息。
就以我自己正在做的項目來說,接收端是一台單頻指標測量儀,它會把當前測量的單頻指標信息通過socket接口發送給服務器,發送包長度約100字節,1s能發送10個包左右,如果我不實時處理粘包,為前台就無法實時展示采集到的單頻指標信息。
下面演示的通信是在之前的框架基礎上增加的一些代碼,首先先創建一個包模擬類生成類PackageBuilder,它可以自動生成長度不一的包,用於測試發送,代碼如下,因為與通信無關所以對裡面的代碼不做說明。

![]()
public static class PackageBuilder
{
static StringBuilder package = new StringBuilder();
public static string[] BuildPackage(int count)
{
Random random = new Random();
int dataLength;
string[] packageArr = new string[count];
int myChar;
for (int j = 0; j < count; j++)
{
dataLength = random.Next(25) + 25;
package.Append("HEAD|H1|"+dataLength);
package.Append("data:");
for (int i = 0; i < dataLength-5; i++)
{
myChar = random.Next(26) + 65;
package.Append((char)myChar);
}
packageArr[j] = package.ToString();
package.Clear();
}
return packageArr;
}
View Code
在main函數中測試一下生成的包

![]()
static void Main(string[] args)
{
string[] str = PackageBuilder.BuildPackage(20);
for (int i = 0; i < 20; i++)
{
// str = PackageBuilder.BuildPackage();
Console.WriteLine(str[i]);
// Thread.Sleep(500);
}
Console.Read();
}
View Code

解決粘包問題有多種方法,根據發送包的結構,我采取的是根據包數據長度分包的方法。
如上圖所示,我們發送包結構為:包頭+數據長度+數據,包頭(HEAD|H1|)是固定長度,內容基本不變,數據長度(兩個字節)是變化的,數據(data:+隨機字符)也是變化的,其中數字之後的所有內容都是數據,包括'data:'。
前奏講完了下篇文章回到socket。