首页 > 解决方案 > 如何获取带有消息结尾字符的 TCP 消息中的所有数据?

问题描述

我有一个 TCP 客户端/服务器应用程序,它在本地机器上运行良好。但是,当我在另一台机器上使用客户端时,只传递了小消息(最多 20-30 个字节)。如果锁定,客户端需要读取更大数据的那一刻。我认为问题在于客户端没有接收到在一个 tcp 数据包中发送的所有数据。所以换句话说,我对 tcpClient.Client.Receive(tcpBuffer) 进行了一次调用,并假设 tcpBuffer 拥有它在本地机器上所做的所有数据。现在,服务器正在发送的消息都以一个字节结束,该字节在消息中是唯一的(0xFD)。我不知道如何处理这个问题。所以一个问题是,是NetworkStream。DataAvailable 为您提供客户端或服务器上可用的数据?在获得 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
    }
}

所以从上面可以看出我挂断电话的地方。我只是做另一个接收吗?如果还没有数据怎么办?谢谢,汤姆

标签: c#.netsocketstcpclient

解决方案


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();
}

推荐阅读