TCP粘包分包问题的解决方案

1.在我们写TCP服务端的时候经常会出现粘包和分包的问题把,这里让我来分享我的结局方案把。

原理:之所以会出现粘包是TCP为了节约性能做出的处理,我们可以通过对数据的处理来进行解决这个问题。
TCP粘包分包问题的解决方案_第1张图片

客户端

**我们可以通过在客户端发送请数据的时候把客户端的数据长度放在数据长度放在数据前转换成Byte类型一起发送给客户端;

客户端代码如下

   Socket socket_Cliect = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
        //接收消息
        socket_Cliect.Connect(new IPEndPoint(IPAddress.Parse("127.0.0.1"),88));


        byte[] data = new byte[1024];
        int count = socket_Cliect.Receive(data);
        string msg = Encoding.UTF8.GetString(data, 0, count);
        Console.Write(msg);
    

        for (int i = 0; i < 104; i++)
        {
            socket_Cliect.Send(Message.GetBytes(i.ToString()));
        }
        Console.ReadKey();
        socket_Cliect.Close();
       

处理客户端代码如下

  class Message
    {
        private byte[] data = new byte[1024];

        //我们存储了多少个字节的数据在数据里
        private int StartIndex = 0;

        public void AddCout(int cout)
        {
            StartIndex += cout;
        }

        public byte [] Data
        {
            get { return data; }
        }
        public int StartIndexa
        {
            get { return StartIndex; }
        }
        public int ReamainSize
        {
            get { return data.Length - StartIndex; } 
        }
        /// 
        /// 解析数据,读取数据
        /// 
        public void ReadMessage()
        {
            while (true)
            {
                if (StartIndex <= 4) return;
                int cout = BitConverter.ToInt32(data, 0);
                if (StartIndex - 4 >= cout)
                {
                    string s = Encoding.UTF8.GetString(data, 4, cout);
                    Console.WriteLine("解析一条数据:" + s);
                    //从Cout+4开始复制  ,拷贝长度为S
                    Array.Copy(data, cout + 4, data, 0, StartIndex - cout);
                    StartIndex -= (cout + 4);
                }
                else  {   return; }
            }
        }

服务端代码如下:

   static void Main(string[] args)
        {
            StartServerAsync();
            Console.ReadKey();
        }

        static void StartServerAsync()
        {
            Socket serverSocker = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
            //IP:127.0.0.1
            IPAddress iPAddress = IPAddress.Parse("127.0.0.1");
            IPEndPoint iPEndPoint = new IPEndPoint(iPAddress, 88);

            serverSocker.Bind(iPEndPoint);

            //开始监听
            serverSocker.Listen(0);

            //接收客户端连接//接受客户端数据
            //Socket clienScocket = serverSocker.Accept();
            //开始异步接收
          serverSocker.BeginAccept(AcceptCallBack, serverSocker);

        }
        #region 异步接收
        static Message msg = new Message();
        static void AcceptCallBack(IAsyncResult ar)
        {
            Socket serverScocker = ar .AsyncState as Socket;
            Socket clienScocket = serverScocker.EndAccept(ar);
            //向客户端进行发送消息
            string msgStr = "Hello client! 你好......";
            byte[] data = Encoding.UTF8.GetBytes(msgStr);
            clienScocket.Send(data);

            //异步接收
            clienScocket.BeginReceive(msg.Data, msg.StartIndexa, msg.ReamainSize, SocketFlags.None, ReceiveCallBack, clienScocket);
            //回调异步等待
            serverScocker.BeginAccept(AcceptCallBack, serverScocker);
        }

        static byte[] dataBuffer = new byte[1024];
       
        static void ReceiveCallBack(IAsyncResult ar)
        {
            Socket clientSocket =null;
           
            try
            {
                clientSocket = ar.AsyncState as Socket;
                int cout = clientSocket.EndReceive(ar);
                if(cout == 0)
                {
                    clientSocket.Close();
                    return;
                }
                msg.AddCout(cout);
                //string msgStr = Encoding.UTF8.GetString(dataBuffer, 0, cout);
                //Console.WriteLine("从客户端接收到数据:" + msgStr);

                //数据解析(循环解析)
                msg.ReadMessage();
                clientSocket.BeginReceive(msg.Data, msg.StartIndexa, msg.ReamainSize, SocketFlags.None, ReceiveCallBack, clientSocket);
            }
            catch (Exception e)
            {
                Console.Write(e);
                if (clientSocket != null)
                {
                    clientSocket.Close();
                }
            }
        }

        #endregion
        //同步
        static void StartServerSync()
        {
            Socket serverSocker = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
            //IP:127.0.0.1
            IPAddress iPAddress = IPAddress.Parse("127.0.0.1");
            IPEndPoint iPEndPoint = new IPEndPoint(iPAddress, 88);

            serverSocker.Bind(iPEndPoint);

            //开始监听
            serverSocker.Listen(0);

            //接收客户端连接//接受客户端数据
            Socket clienScocket = serverSocker.Accept();

            //向客户端进行发送消息
            string msg = "Hello client! 你好......";
            byte[] data = Encoding.UTF8.GetBytes(msg);
            clienScocket.Send(data);

            //接受客户端的一条消息
            byte[] dataBuffer = new byte[1024];
            int cout = clienScocket.Receive(dataBuffer);

            string msResveive = Encoding.UTF8.GetString(dataBuffer, 0, cout);
            Console.WriteLine(msResveive);
            Console.ReadKey();
            clienScocket.Close();
            serverSocker.Close();
        }

处理模块代码如下:

  private byte[] data = new byte[1024];

    //我们存储了多少个字节的数据在数据里
    private int StartIndex = 0;

    public void AddCout(int cout)
    {
        StartIndex += cout;
    }

    public byte [] Data
    {
        get { return data; }
    }
    public int StartIndexa
    {
        get { return StartIndex; }
    }
    public int ReamainSize
    {
        get { return data.Length - StartIndex; } 
    }
    /// 
    /// 解析数据,读取数据
    /// 
    public void ReadMessage()
    {
        while (true)
        {
            if (StartIndex <= 4) return;
            int cout = BitConverter.ToInt32(data, 0);
            if (StartIndex - 4 >= cout)
            {
                string s = Encoding.UTF8.GetString(data, 4, cout);
                Console.WriteLine("解析一条数据:" + s);
                //从Cout+4开始复制  ,拷贝长度为S
                Array.Copy(data, cout + 4, data, 0, StartIndex - cout);
                StartIndex -= (cout + 4);
            }
            else  {   return; }
        }
       
    }

来源于一个大二在校生。

你可能感兴趣的:(TCP)