首页 文章

TCP服务器未正确读取固定大小的消息

提问于
浏览
2

我将传感器数据从Android设备发送到C#中的TCP服务器 . android客户端以32字节的固定大小块发送数据 .

在服务器中,我读取数据,期望它将以完整包形式出现,但由于TCP是流协议,因此一些消息到达服务器分为两部分 . 我知道,因为我可以使用名为SocketSniff的软件观看它 .

问题是我不知道如何在我的服务器上处理它 .

我发现的所有例子都使用了 NetworkStream.Read() ,在这个方法中我必须传递一个字节数组来存储数据读取,一个偏移量和要读取的字节数 . 这个字节数组必须具有已知大小,在我的例子中为32 .

我不知道到达我服务器的邮件的实际大小,但它可能是以下情况之一 .

  • 如果收到的数据大小为32字节,则一切正常 .

  • 如果收到的数据大小超过32个字节,我想我正在丢失数据 .

  • 如果接收的数据大小小于32个字节,假设为20个字节,则这些字节存储在我的数组中,并且数组的最后12个字节保留为零值 . 由于我可能真的收到一些零,所以无法知道我真正收到的大小,因此我无法将其与剩下的数据合并,这些数据应该在下次阅读时出现 .

我处理接收的代码如下:

int buffer = 32;
    ...
    private void HandleClientComm(object client)
    {
        TcpClient tcpClient = (TcpClient)client;
        NetworkStream clientStream = tcpClient.GetStream();

        byte[] message = new byte[buffer];
        int bytesRead;

        while (true)
        {
            bytesRead = 0;

            try
            {
                bytesRead = clientStream.Read(message, 0, message.Length);
            }
            catch
            {
                break;
            }

            if (bytesRead == 0)
            {
                // Connection closed
                break;
            }

            SensorData sensorData = ProcessTcpPacket(message);
        }
        tcpClient.Close();
    }

有没有办法知道我在套接字中收到的数据大小?

1 回答

  • 6

    嗯,是的,你有bytesRead变量 - 它保存从流中读取的字节数 . 您将最多读取message.Length字节,但您可以阅读更少 .

    请注意,如果有更多可用字节,则只需读取message.Length字节即可丢失它们 . 相反,它们将在您下次从流中读取时可用 .

    你需要做的是添加另一个while循环喜欢这个:

    int messageRead = 0;
    
    while(messageRead < message.Length)
    { 
        int bytesRead = clientStream.Read(message, messageRead, message.Length - messageRead);
        messageRead += bytesRead;
        if(bytesRead==0)
            return;   // The socket was closed
    }
    // Here you have a full message
    

相关问题