关于Socket粘包问题

我们有时候在频繁使用socket传输消息、消息太长时,可能会遇到粘包问题,使得数据错乱,无法使用;

解决办法(大概思路):

在传输时规定在有效数据前增加4个字节,用来存放有效字符的字节长度;解析数据的时候只需要先取出四个字节获取有效数据的字节长度,判断接受字节数组大于4+有效长度的时候取出解析数据,剩余留存下次处理。ps:不知道说清楚了没。上代码

public class Message  {

    private byte[] data = new byte[1024];
    private int startIndex = 0;
    private int remainSize;

    public byte[] Data
    {
        get { return data; }
    }

    public int StartIndex
    {
        get { return startIndex; }
    }
    public int RemainSize
    {
        get
        {
            remainSize = data.Length - startIndex;
            return remainSize;
        }
    }
 //解析信息
    public void ReadMassage(int newDataAmount, Action< string> processDataCallBack)
    {
        startIndex += newDataAmount;
        while (true)
        {
            if (startIndex <= 4) return;//小于长度
            int dataCount = BitConverter.ToInt32(data, 0);//数据长度
            Debug.Log(startIndex);
            if (startIndex - 4 >= dataCount)
            {
                string str = Encoding.UTF8.GetString(data, 4, dataCount );
                processDataCallBack( str);
            
                Array.Copy(data, dataCount + 4, data, 0, startIndex - dataCount - 4);
                startIndex -= (dataCount + 4);
            }
            else
            {
                break;
            }
        }
    }
//打包消息
 public static byte[] PackData( string data)
    {
        byte[] dataBytes = Encoding.UTF8.GetBytes(data);
        int dataAmount = dataBytes.Length;
        byte[] dataAmountBytes = BitConverter.GetBytes(dataAmount);

        return  dataAmountBytes.Concat(dataBytes).ToArray();
    }
}

上面消息处理工具;

下面使用例子:

 以udp为例
//发送消息 
void SocketSend(string sendStr, EndPoint clientEnd)
    {
        sendData = new byte[1024];
        sendData = Message.PackData(sendStr);
        socket.SendTo(sendData, sendData.Length, SocketFlags.None, clientEnd);
    }
//接受消息
  void SocketReceive()
    {
        while (true)
        {
          
            recvLen = socket.ReceiveFrom(message.Data,message.StartIndex,message.RemainSize,SocketFlags.None, ref clientEnd);
          
            message.ReadMassage(recvLen, OnDataCall);
        }
    }
 //处理数据
    private void OnDataCall(string data)
    {
        Dug.log("收到的数据为:"+data);
    }

有不对的地方欢迎各位大佬指正!!!

 

你可能感兴趣的:(关于Socket粘包问题)