通过TCP拆分消息

时间:2018-12-04 14:30:56

标签: c# c++ server

我在uni项目中遇到了一些麻烦。我从C ++客户端向C#服务器发送tcp消息,服务器分两部分接收它。有可能阻止它下来吗?我输出正在客户端发送的数据,所有数据都在1件中,所以不能这样。这是我的OnReceiveData方法:

void OnReceiveData(IAsyncResult result){
        try{
            int readbytes = myStream.EndRead(result);
            if (readbytes <= 0){
                //client is not connected to the server anymore
                CloseSocket();
                return;


            byte[] newBytes = new byte[readbytes];
            Buffer.BlockCopy(readBuff, 0, newBytes, 0, readbytes);
            myStream.BeginRead(readBuff, 0, readbytes, OnReceiveData, 
            null);
            string output = 
            System.Text.Encoding.ASCII.GetString(newBytes, 0, 
            readbytes);
            Text.WriteLog(output);

            ServerHandleData.HandleData(connectionID, newBytes);
        }
        catch (Exception e)
        {
            Text.WriteError("Error Code: " + e);
            CloseSocket();
        }
    } 

谢谢!

3 个答案:

答案 0 :(得分:1)

没有办法“阻止它”,这就是 TCP的工作方式。

简而言之,由于TCP正在流式传输,因此没有消息边界。只是连续的字节流。

要在数据之间实现某种消息传递或边界,那么您需要提出自己的应用程序层协议以放在TCP之上。例如,您可以引入某种消息边界令牌,特殊字符,字节或字符/字节序列,这表示当前消息已结束。或者,您可以发送固定大小的消息头,其中包括实际消息数据的大小。

然后,在接收时,您需要循环接收,直到您检测到消息结尾。为此,最简单的方法是使用具有数据长度的固定大小的标头,因为您只需尝试读取(标头或数据的)长度,减少接收每次迭代的字节数,直到没有更多内容为止接收(接收的字节数达到零)。

答案 1 :(得分:1)

不,TCP是流,而不是单个“大块”数据。

the EndRead example中所见,一条消息可能被分成多个部分,因此您必须阅读这些部分并将其连接起来。

readbytes = myStream.EndRead(result);
myCompleteMessage = String.Concat(myCompleteMessage,
                                  Encoding.ASCII.GetString(myReadBuffer, 0,
                                                           readbytes));    

// message received may be larger than buffer size so loop through until you have it all.
while(myStream.DataAvailable) {

    myStream.BeginRead(myReadBuffer, 0, myReadBuffer.Length,
                       new AsyncCallback(NetworkStream_ASync_Send_Receive.myReadCallBack),
                                         myStream);  
}

答案 2 :(得分:0)

所以一段时间后,我设法修复了它。问题是开始读取中的读取字节被设置为先前的消息长度,这迫使它拆分消息。我是通过手动设置尺寸来解决的。

感谢您的建议! :)