當socket接收到數據后,會根據buffer的大小一點一點的接收數據,比如:
- 對方發來了1M的數據量過來,但是,本地的buffer只有1024字節,那就代表socket需要重復很多次才能真正收完這邏輯上的一整個消息。
- 對方發來了5條2個字符的消息,本地的buffer(大小1024字節)會將這5條消息全部收入囊下...
那么,如何處理呢?下面我以最簡單的一種文本消息來demo
根據上面所描述的情況,最重要的關鍵落在了下面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); }
組件代碼下載