Socket 循环接收消息 粘包 半包(C#)

NetWork 同时被 2 个专栏收录
18 篇文章 0 订阅
36 篇文章 1 订阅

这两天在向同事学习socket收发消息的问题,学到了新知识,非常感谢 yss 的 hwh

1、对于一次接收到大于接收缓存的消息,并且连续接收消息,两段消息可能同时被接受到一端缓存中,叫粘包;

2、收到的消息不足一个接收缓存,交半包;

 

程序的几个注意点:

1、必须要循环接收消息;

2、消息头必须要有长度标志字节(这里是用的前四个字节来保存实际消息体的长度);

3、除了接收缓存rev之外还需要一个cache缓存byte[] ,用来保存一条完整的消息;

4、cache缓存可能不足一个接收缓存,那后面不足的会有\0 补充 ,半包;

5、cache缓存 可能刚好一个接收缓存,并且包含>= 1个完整消息(等于的时候无粘包,大于的时候有粘包);

6、cache缓存 大于一个接收缓存,这里需要循环接收(用长度标志字节来判断),直到接收到 >= 一个完整消息,还是5、的情况;

7、接受完一个完整消息后,需要清空缓存,或者将有粘包的字节重新拷贝到cache缓存;

 

以下是代码实现:

Socket soc = obj as Socket;
int recvlen = 0;
byte[] cacheBuf = null;
byte[] recvBuf = new byte[100];
if (soc != null)
{
    while ((recvlen = soc.Receive(recvBuf)) > 0)
    {
        if (cacheBuf == null)
        {
            cacheBuf = new byte[recvlen];
            Array.Copy(recvBuf, cacheBuf, recvlen);
        }
        else
        {
            byte[] t = new byte[cacheBuf.Length + recvlen];
            Array.Copy(cacheBuf, t, cacheBuf.Length);
            Array.Copy(recvBuf, 0, t, cacheBuf.Length, recvlen);
            cacheBuf = t;
        }
        if (cacheBuf.Length <= 4)
            continue;
        int msgl = BitConverter.ToInt32(cacheBuf, 0);
        while (cacheBuf!=null && msgl + 4 <= cacheBuf.Length)
        {
            byte[] msgbyte = new byte[msgl];
            Array.Copy(cacheBuf, 4, msgbyte, 0, msgl);
            test(msgbyte,soc);//拿到完整消息,具体消息操作
            if (msgl + 4 == cacheBuf.Length)
            {
                cacheBuf = null;
            }
            else
            {
                byte[] tmpByte = new byte[cacheBuf.Length - msgl - 4];
                Array.Copy(cacheBuf, msgl + 4, tmpByte, 0, cacheBuf.Length - msgl - 4);
                cacheBuf = tmpByte;
            }
        }
    }
}

 

 

 

  • 3
    点赞
  • 3
    评论
  • 5
    收藏
  • 一键三连
    一键三连
  • 扫一扫,分享海报

©️2021 CSDN 皮肤主题: 精致技术 设计师:CSDN官方博客 返回首页
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值