无法获取SslStream的可用字节数

时间:2016-10-27 18:48:15

标签: .net network-programming sslstream

我正在尝试确定可读取的字节数,因此我可以从SslStream读取,直到读取完所有数据。 SslStream似乎没有属性或方法来执行此操作,因此我一直在尝试使用基础Socket。这里的问题是Socket报告的可用字节数与我需要的实际解密数据量不匹配。

这是我的接收方法:

byte[] Receive()
{
    byte[] messageBuffer = new byte[4096];
    int bytesRead = 0;

    using (var readData = new MemoryStream())
    {
        while(Client.Client.Available > 0)
        {
            bytesRead = Stream.Read(messageBuffer, 0, messageBuffer.Length);
            readData.Write(messageBuffer, 0, bytesRead);
        }

        return readData.ToArray();
    }
} 

Client.ClientSocket的基础Stream,即SslStream。假设消息大小为5000字节。这里有几个问题:

  1. 首次尝试阅读Client.Client.Available会返回5077.这不是可用数据的正确长度。
  2. 第一次调用Stream.Read之后Client.Client.Available返回0,所以我退出循环,即使我只读了4096,因为那是我的缓冲区大小。因此,流上还剩下904个字节尚未读取。
  3. 所以看来,在我调用Stream.Read后,它会从Socket中删除整个数据(所有5000个字节不仅仅是我要求的4096),这是有道理的,因为你需要整个消息来解密它。但是,由于没有SslStream.Available或任何类型的东西,因此无法知道您是否已收到整条消息。所以我的问题是如何判断我是否收到了完整的解密信息? (或者我如何获得解密消息的字节数?)

    我尝试过的其他事情:

    • 使用Client.Client.Poll(someLongTimeoutForTesting, SelectMode.SelectRead),但在第一个Stream.Read之后返回false。
    • 再次使用Client.GetStream().DataAvailable在第一个Stream.Read
    • 后返回false
    • 将messageBuffer的大小增加到最大量Stream.Read将返回(16299,不知道为什么这个数字,但是当我增加消息大小和缓冲区大小超过此Stream.Read()时总是返回16299)。这种方法有效,但它使用了不合理的内存量,因为在应用程序中它将在客户端消息中使用的时间低于4096 99.99%。

2 个答案:

答案 0 :(得分:0)

如果你知道消息的长度,你可以读取数组的字节,然后从这个数组创建流:

    buffer = new byte[num_of_bytes];
    for (int i = 0; i < num_of_bytes; i++)
        buffer[i] = (byte)sslStream.ReadByte();

    using (var stream = new MemoryStream(buffer))
    {                   
    }

答案 1 :(得分:0)

使用TCP套接字(流)时,需要实现自己的应用层协议。一个非常简单的解决方案:您在前两个字节中指明消息大小(例如,它可能是您决定的长度),您还可以为消息类型分配一个或两个字节(例如),其余为有效负载。因此,您知道始终前两个字节表示长度,因此您必须读取2个字节。然后你得到有效载荷长度。那一刻你知道要读多少字节。我用更多细节解释它,而不是SslStream,但响应也适用于你的情况,在这里:How to read all of Inputstream in Server Socket JAVA