我有一个带有持久套接字的应用程序(它在应用程序启动时打开并与应用程序一起关闭)。
服务器使用此套接字来推送一些数据。
由于此连接可以是 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);
}
这是我的2个问题:
文档说如果没有数据可用,Read 方法返回 0。但在我的情况下,Read 要么返回一个数字 > 0(当某些数据已被读取时),要么因为超时而引发异常......我在这里错过了什么?Read在什么情况下返回0?
当我的连接使用 HTTP 协议时,此代码可以正常工作。我收到所有内容,如果消息大于我的缓冲区大小 (CST_STREAM_BUFFER_SIZE),DataAvailable 保持为真,循环读取所有剩余数据。但是当我尝试使用 HTTPS 时,它仅适用于小于我的缓冲区的消息。如果消息更大,则方法 Read 首先读取 CST_STREAM_BUFFER_SIZE 字节,然后 DataAvailable 变为 false,尽管某些字节显然已准备好读取。在这种情况下,接收另一条消息会“解开”剩余数据,因为 DataAvailable 再次变为真。我究竟做错了什么?为什么 DataAvailable 在这两种情况下的行为不同?
任何帮助,将不胜感激。