我正在尝试确定可读取的字节数,因此我可以从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.Client
是Socket
的基础Stream
,即SslStream
。假设消息大小为5000字节。这里有几个问题:
Client.Client.Available
会返回5077.这不是可用数据的正确长度。Stream.Read
之后Client.Client.Available返回0,所以我退出循环,即使我只读了4096,因为那是我的缓冲区大小。因此,流上还剩下904个字节尚未读取。所以看来,在我调用Stream.Read
后,它会从Socket中删除整个数据(所有5000个字节不仅仅是我要求的4096),这是有道理的,因为你需要整个消息来解密它。但是,由于没有SslStream.Available
或任何类型的东西,因此无法知道您是否已收到整条消息。所以我的问题是如何判断我是否收到了完整的解密信息? (或者我如何获得解密消息的字节数?)
我尝试过的其他事情:
Client.Client.Poll(someLongTimeoutForTesting, SelectMode.SelectRead)
,但在第一个Stream.Read
之后返回false。 Client.GetStream().DataAvailable
在第一个Stream.Read
Stream.Read()
时总是返回16299)。这种方法有效,但它使用了不合理的内存量,因为在应用程序中它将在客户端消息中使用的时间低于4096 99.99%。 答案 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