什么是粘包?
比如:通过Socket发2条不一样长度的数据,"abc"和"defg"。因为Socket的数据不是你请求发就立即发送的,有时候为了减少网络交互次数,会把几小的个数据凑一凑一起发送。
如果前面的被凑到一起发送了"abcdefg",就出现了粘包。
如何解决粘包问题?
发送数据的时候,在数据里带上这个数据的长度信息,这样就算多个数据被凑在一起发送,我们也能根据每个数据的长度信息来把他们区分出来。
上面的数据就变成:3abc,4defg;其中:3表示3个字节,utf-8字符串abc占3个字节;4表示4个字节。
代码
private const int Packet_Head_Len = 4; //包头4字节, 一个int private void RecvLoop(Socket socket) { byte[] buff = new byte[8 * 1024]; //假设单个数据包不会超过这个大小 byte[] temp4Bytes = new byte[4]; int packetRecvLen = 0; while (true) { try { int buffRemainLen = buff.Length - packetRecvLen; if (buffRemainLen <= 0) //数据包超过buff的大小了 break; int recvLen = socket.Receive(buff, packetRecvLen, buffRemainLen, 0, out var errCode); if (0 == recvLen) //服务端把该连接Shutdown或Close了 break; packetRecvLen += recvLen; if (IsPacketReady(packetRecvLen, buff, temp4Bytes, out var bodyLen)) { var str = Encoding.UTF8.GetString(buff, Packet_Head_Len, bodyLen); //todo: 数据包处理 packetRecvLen -= Packet_Head_Len; //包头 packetRecvLen -= bodyLen; //下一个包的数据 if (packetRecvLen > 0) //如果有下一个包的数据, 移到buff开头 Buffer.BlockCopy(buff, Packet_Head_Len + bodyLen, buff, 0, packetRecvLen); } } catch (Exception ex) { //todo: 打印错误信息 } } } //检查数据是否都已经接收到了 public static bool IsPacketReady(int packetRecvLen, byte[] buff, byte[] temp4Bytes, out int bodyLen) { bodyLen = 0; if (packetRecvLen < Packet_Head_Len) return false; Buffer.BlockCopy(buff, 0, temp4Bytes, 0, 4); bodyLen = BitConverter.ToInt32(temp4Bytes, 0); if (packetRecvLen < Packet_Head_Len + bodyLen) return false; return true; }
标签:packetRecvLen,Socket,int,粘包,byte,接收,buff From: https://www.cnblogs.com/sailJs/p/17977800