粘包分包现象及处理


现象描述


由于TCP协议本身的机制

客户端与服务器会维持一个连接发送数据


粘包原因

如果发送的网络数据包太小,TCP则会合并较小的数据包再发送,

接收端便无法区分哪些数据是发送端自己分开的,

因此便会产生粘包现象。

或者,接收端把数据放到接收缓冲区中,

如果数据没有及时从缓冲区取走,

下次取数据时就可能出现一次取走多个数据包的情况。

如:

客户端Send:hello

客户端Send:unity

服务端Recv:Recv


分包原因

如果发送的数据包太大,TCP有可能会将它拆分成多个包发送

接收端的一次Receive可能只收到一部分数据。

如:

客户端Send:hellounity

服务端Recv:hel

服务端Recv:lounity


处理办法


每个数据包前加上长度字节


如果缓冲区的数据长度大于要提取的字节数

则取出相应的字节

否则等待下一次数据接收


代码实现


private void ProcessData(Conn conn) {
         //小于字节长度
         if (conn.buffCount < sezeof(Int32))
             return;
         
         //消息长度
         Array.Copy(conn.readBuff,conn.lenBytes,sizeof(Int32));
         conn.msgLength = BitConverter.ToInt32(conn.lenBytes,0);
         if(conn.buffCount < conn.msgLength + sizeof(Int32))
             return;
             
         //处理消息
         string str = System.Text.Encoding.UTF8.GetString(conn.readBuff,sizeof(Int32),conn.msgLength);
         Console.WriteLine("收到消息["+conn.GetAdress() + "]" + str);
         Send(conn,str);
         
         //清除已处理的消息
         int count = conn.buffCount - conn.msgLength = sizeof(Int32);
         Array.Copy(conn.readBuff,sizeof(Int32) + conn.msgLength,conn.readBuff,0,count);
         conn.buffCount = count;
         if(conn.buffCount > 0){
             ProcessData(conn);
         }
}


当然,这段代码是无法直接复制粘贴使用的

因为里面涉及到了很多其他的API

在这里只需要了解实现的方式即可

原文地址:https://www.cnblogs.com/fws94/p/7127552.html