TCP Socket消息包头4字节发生"粘包"现象,4字节长度有时候不在networksstream缓冲区首位,导致数据错乱

我翻阅大量书籍资料选择了消息长度包头4字节+消息内容协议接收数据时,包头4字节发生"粘包"现象,4字节长度有时候不在networksstream缓冲区首位,导致数据错乱,请问有什么解决办法,平台是C#,长连接。代码如下:

private void AccepMessage()
        {
            NetworkStream netStream = new NetworkStream(socket);
            while (true)
            {
                try
                {
                    byte[] datasize = new byte[4];
                    netStream.Read(datasize, 0, 4);//先读取长度4字节 
                    int size = System.BitConverter.ToInt32(datasize, 0);
                    Byte[] message = new byte[size];
                    int dataleft = size;
                    int start = 0;
                    while (dataleft > 0)
                    {
                        int recv = netStream.Read(message, start, dataleft);//再读数据内容
                        start += recv;
                        dataleft -= recv;
                    }
                    this.rchTxtBoxReceive.Text = System.Text.Encoding.Unicode.GetString(message);
                }
                catch
                {
                    
                }
            }
        }
冥思苦想数日,感觉碰了墙,请指点迷津。
如果包头长度4字节错位不在缓冲区首位,有什么方法可以移到首位?似乎要加开始符索引?

另外 如果表示包头长度的4字节本身粘包了咋办?

在取包头4字节那,也要判断是否取得了4字节,不够继续获取。和下面取包体一样

如果包头4字节不在流的首位怎么办?

没有什么首位不首位的,要多少个字节给你多少字节,数据流跟水流一样,没有什么首位。你先按我说的试试

我的意思是:length+body,如是length本身粘包了咋办,比如body+length+body,gth+body+len,如果长度头自身不完整,也就不法读到正确的消息。

我们不管他是不是在缓冲区首位

如果不讲啥内存效率的化,简单伪代码是

 indexof(span<byte>xxx ,"头部特征")--------查找第一个头部特征所在index
 然后所有的操作都是从这个index开始,从这个index 向后提取,到符合尾部

  如果查到尾部,删除尾部之前所有的数据,只保留尾部以后的数据。如果没有查到尾部,那就啥都不操作,留着(当然正常简单处理到这就差不多了,如果是复 杂比如怕伪造大数据封包,可以带检查条件,不符合条件的,从index再往后查第一个匹配头部特征的,也就是既然前一个不符合规则,扔掉检查下一个头部)

重复上述动作

我是先接收满4字节,计算出包长度后,再根据长度接收指定长度字节数,不管后面还有没有数据,直接截断,算小蜜蜂论坛发帖机一个包,后面的数据都算下一个包,再接收4个字节,算长度。。。。。。。

4字节长度信息不完整、截断粘包咋办。不够4字节就继续接啊

用以下代码去收4个字节:
var bytes4 = ReadAllBytes(netStream, 4);


// ReadAllBytes你还可以写成一个扩展方法。还可以自己实现异步的ReadAllBytesAsync。
public static byte[] ReadAllBytes(Stream stream, int count)
{
    var bytes = new byte[count];
    for(var offset = 0; offset<count;)
    {
        var read = stream.Read(bytes, offset, count - offset);
        if (read == 0) throw new IOException("Unexpect end of stream");

        offset += read;
    }
    return bytes;
}

请测试几个问题:
1:TCP短连接会有粘包问题吗?
2:TCP长连接不同连接传的数据会粘包吗?

现在正在接联通SGIP,人家定义的头格式不也类似吗?
4.2.2消息头的格式
字段 长度(字节) 类型 说明
Message Length 4 Integer 消息的总长度(字节)
Command ID 4 Integer 命令ID
Sequence Number 12 Integer 序列号
表4-14消息头的格式

  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值