【问题标题】:NetworkStream.DataAvailable property does not return the right result when using SslStream使用 SslStream 时,NetworkStream.DataAvailable 属性不返回正确的结果
【发布时间】:2011-06-21 11:24:13
【问题描述】:

我有一个带有持久套接字的应用程序(它在应用程序启动时打开并与应用程序一起关闭)。

服务器使用此套接字来推送一些数据。

由于这个连接可以是 HTTP 或 HTTPS,我编写了这段代码来初始化我的对象:

s_tcpClient = new TcpClient(s_server.CometIp, s_server.CometPort);
s_tcpClient.Client.SetSocketOption(SocketOptionLevel.Socket, SocketOptionName.KeepAlive, false);
s_tcpClient.Client.SetSocketOption(SocketOptionLevel.Socket, SocketOptionName.ReceiveBuffer, CST_STREAM_BUFFER_SIZE);
s_tcpClient.ReceiveTimeout = 0;

s_networkStream = s_tcpClient.GetStream();

s_cometStreamReader = null;

if (s_server.Protocol == "HTTPS")
{
    SslStream sslStream = new SslStream(
        s_tcpClient.GetStream(),
        false,
        new RemoteCertificateValidationCallback(ValidateServerCertificate)
    );

    sslStream.AuthenticateAsClient(s_server.CometIp);
    s_cometStreamReader = new StreamReader(sslStream, Encoding.UTF8, true, CST_STREAM_BUFFER_SIZE);
    s_cometStream = sslStream as Stream;
}
else
{
    s_cometStreamReader = new StreamReader(s_networkStream, Encoding.UTF8, true, CST_STREAM_BUFFER_SIZE);
    s_cometStream = s_networkStream as Stream;
}

这样,我可以同时处理 HTTP 和 HTTPS 协议。

然后,我得到了这个循环(在一个线程中),它等待数据在套接字中可用:

while (s_networkStream.DataAvailable)
{
    numberOfBytesRead = s_cometStream.Read(buffer, 0, buffer.Length);
    message.Append(Encoding.UTF8.GetString(buffer, 0, numberOfBytesRead));
    ExtractMessages(ref message);
}

这是我的两个问题:

  1. 文档说如果没有可用数据,Read 方法会返回 0。但在我的情况下,Read 要么返回一个数字 > 0(当某些数据已被读取时),要么因为超时而引发异常......我在这里错过了什么? Read在什么情况下返回0?

  2. 当我的连接使用 HTTP 协议时,此代码可以正常工作。我收到所有内容,如果消息大于我的缓冲区大小 (CST_STREAM_BUFFER_SIZE),DataAvailable 保持为真,循环读取所有剩余数据。 但是当我尝试使用 HTTPS 时,它仅适用于小于我的缓冲区的消息。如果消息更大,则 Read 方法首先读取 CST_STREAM_BUFFER_SIZE 字节,然后 DataAvailable 变为 false,尽管某些字节显然已准备好读取。 在这种情况下,接收另一条消息会“解开”剩余数据,因为 DataAvailable 再次变为真。 我究竟做错了什么?为什么 DataAvailable 在这两种情况下的行为不同?

任何帮助将不胜感激。

【问题讨论】:

  • 没人知道我做错了什么,在这里?
  • 我的问题是很难回答还是只是愚蠢?我真的很想了解这里发生了什么......

标签: c# .net sslstream


【解决方案1】:

如果流关闭,它只会返回 0,因此不会有更多数据永远到来。否则,如果可以读取数据,则为正数,如果尚无数据可用,则可能涉及阻塞。如果CanTimeout 为真,则操作将在ReadTimeout 通过且无可用数据后抛出。

听起来可能是套接字一直处于打开状态和/或您试图读取太多内容您有一个协议可以在对话中发送多个数据块。

http://msdn.microsoft.com/en-us/library/system.io.stream.readtimeout.aspx

【讨论】:

  • 好的,谢谢。这回答了我的第一个问题。你是一个回答我的人,这是一个非常奇怪的巧合,因为我昨天尝试了你的 protobuf-net。 ;o)
  • @Rodolphe - 有任何问题,请告诉我。
猜你喜欢
  • 2020-02-18
  • 2012-04-11
  • 2016-02-06
  • 2017-05-09
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多