代码之家  ›  专栏  ›  技术社区  ›  Tom

如何获取带有消息结尾字符的TCP消息中的所有数据?

  •  0
  • Tom  · 技术社区  · 6 年前

    我有一个tcp客户机/服务器应用程序,在本地计算机上运行得非常好。然而,当我在另一台机器上使用客户机时,只传递了一些小消息(最多20-30字节)。客户端需要读取更大数据的分钟(如果会锁定)。我认为问题是客户端没有在一个tcp包中接收所有发送的数据。换言之,我只调用了tcpclient.client.receive(tcpbuffer),并假设tcpbuffer拥有它在本地计算机上所做的所有数据。现在,服务器发送的消息都以消息中唯一的字节(0xfd)结尾。我不知道该怎么处理。所以一个问题是,networkstream.data available是否提供了客户机或服务器上可用的数据?在得到0xFD值之前,我必须一直读取和循环吗?一个人怎样才能有效地做到这一点呢? 所以基本上我想用如下内容替换tcpclient.client.receive(tcpbuffer):

    private static byte[] GetTcpResponse()
    {
        int arrayLength = tcpClient.Client.Receive(tcpBuffer);
        if (tcpBuffer[arrayLength - 1] == 0xFD)
        {
           return tcpBuffer;
        }
        else
        {
            //this is where I am hung up
        }
    }
    

    所以我被挂起来的地方可以从上面看出来。我只是做另一个接收吗?如果还没有数据呢? 谢谢,汤姆

    1 回复  |  直到 6 年前
        1
  •  2
  •   Tom    6 年前

    TCP是 基于流的 协议,是的 基于数据报 协议。您不应该依赖于接收到的具有给定大小的数据报,或者您的数据位于任何给定的数据报边界;也不应该期望您的所有数据都在一个数据报(或任何给定数量的数据报)上接收。所以当你说:

    在得到0xFD值之前,我必须一直读取和循环吗?

    是的,这就是重点; 但是 添加一个合理的超时和适当的异常检查,以便在连接失败时应用程序不会挂起,并且永远不会得到终止值。

    你的代码可能是这样的(除了超时、错误检查等);我没有测试过它,但它应该可以帮助你得到这样的想法:

    private static byte[] GetTcpResponse()
    {
        var data = new List<byte>();
        var buffer = new byte[512]; //size can be different, just an example
        var terminatorReceived = false;
        while(!terminatorReceived)
        {
            var bytesReceived = tcpClient.Client.Receive(buffer);
            if(bytesReceived > 0)
            {
                data.AddRange(buffer.Take(bytesReceived));
                terminatorReceived = data.Contains(0xFD);
            }
        }
        return data.ToArray();
    }