目录
概述
socket接收消息的时候经常会出现粘包和断包的问题。
比如:
发送的时候有1000个字节,但是一次接收只有600个字节。即一条完整的消息在接收的时候断开了
两次发送分别发送了1000个字节,但是一次接收到了1500个字节,第二次才收到另外500个字节。即一条完整的消息在一次接收的时候还额外收到了其他消息的部分数据,甚至一次多条数据。
这里尝试的解决办法是对每个消息拆分为几个部分,其中最重要的是消息头header和消息长度len。
当我们收到消息的时候首先判定header当前字节是否为一条消息的开始,然后利用len字段可以知道当前收到的数据是否完整。
主要的处理有三块:
- 构建消息头
- 尝试获取一条完整的消息
- 若某次获取到完整的消息后还有多余的字节则缓存起来继续递归解析消息
构建消息头
其中传入的参数为,tcp接收到的二进制数组。
首先我们让缓存的字节长度超过一个消息头的长度(即header+len的长度,也可以自己额外定义一些其他消息头的内容)
判定消息头的第一个字节为我们字节约定好的header,然后将后面的N个字节解析成int即为单条消息的长度了。
如果第一位不是我们约定好的则直接将整个消息丢掉。
确定好header位,确定好消息长度消息头就构建好了。
// 构建消息头
private bool BuildMessageHead(byte[] mArryRecData)
{
mArryBuffer = CommonTool.CombineArry(mArryBuffer, mArryRecData);
// 未获取到获取消息长度则先获取消息长度
if (intMessageLen == -1)
{
// 头部长度足够
if (mArryBuffer.Length >= TcpData.TCP_HEADER_LEN)
{
// 判定标志位并设置消息长度
if (mArryBuffer[0].Equals(TcpData.TCP_HEAD_MARK))
{
SetMessageLen(mArryBuffer);
return true;
}