C# Socket的粘包處理


當socket接收到數據后,會根據buffer的大小一點一點的接收數據,比如:

  1. 對方發來了1M的數據量過來,但是,本地的buffer只有1024字節,那就代表socket需要重復很多次才能真正收完這邏輯上的一整個消息。
  2. 對方發來了5條2個字符的消息,本地的buffer(大小1024字節)會將這5條消息全部收入囊下...

那么,如何處理呢?下面我以最簡單的一種文本消息來demo

根據上面所描述的情況,最重要的關鍵落在了下面3個因素的處理上

  1. 消息的結尾標記
  2. 接收消息時判斷結尾標記
  3. 當本次buffer中沒有結尾標記時怎么處理

我把寫好的核心算法貼出來:

        StringBuilder sb = new StringBuilder();             //這個是用來保存:接收到了的,但是還沒有結束的消息
        public void ReceiveMessage(object state)            //這個函數會被以線程方式運行
        {
            Socket socket = (Socket)state;
            while(true)
            {
                byte[] buffer = new byte[receiveBufferSize];  //buffer大小,此處為1024
                int receivedSize=socket.Receive(buffer);

                string rawMsg=System.Text.Encoding.Default.GetString(buffer, 0, receivedSize);
                int rnFixLength = terminateString.Length;   //這個是指消息結束符的長度,此處為\r\n
                for(int i=0;i<rawMsg.Length;)               //遍歷接收到的整個buffer文本
                {
                    if (i <= rawMsg.Length - rnFixLength)
                    {
                        if (rawMsg.Substring(i, rnFixLength) != terminateString)//非消息結束符,則加入sb
                        {
                            sb.Append(rawMsg[i]);
                            i++;
                        }
                        else
                        {
                            this.OnNewMessageReceived(sb.ToString());//找到了消息結束符,觸發消息接收完成事件
                            sb.Clear();
                            i += rnFixLength;
                        }   
                    }
                    else
                    {
                        sb.Append(rawMsg[i]);
                        i++;
                    }
                }
            }
        }

這個組件的使用方法: 

           A2DTcpClient client = new A2DTcpClient("127.0.0.1", 5000);
            client.NewMessageReceived += new MessageReceived(client_NewMessageReceived);
            client.Connect();
            client.Send("HELLO");
            client.Close();



        static void client_NewMessageReceived(string msg)
        {
            Console.WriteLine(msg);
        }

 

 組件代碼下載

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM