粘包分包现象及处理
现象描述
由于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
在这里只需要了解实现的方式即可