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

来源:互联网 发布:网络建设方案ppt 编辑:程序博客网 时间:2024/06/10 12:03

这两天在向同事学习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;                            }                        }                    }                }



原创粉丝点击