我正在尝试在屏幕上显示来自ssl流的任何数据(来自网站)。由于我不知道数据何时到达,我使用另一个线程继续从流中读取,直到读取了字节为止。这很完美,但是,我的CPU使用率跃升到25%并保持不变(最大使用量为1个线程,我的PC有4个线程)。虽然这有点有意义,因为线程停留在while循环中,我不期望Thread类的实例占用我的CPU的整个线程(我可以发誓这在使用简单的Client /时没有发生)服务器应用)。
一旦初始化连接,线程就开始运行,用户可以随时将数据发送到网站,应用程序应该打印出响应。对此有什么替代解决方案?我应该删除SslStream并开始使用其他东西吗?
这是在这个单独的线程上运行的代码:
void ReadDataAsync(Object obj) {
byte[] buffer = new byte[65536]; //65536, make sure all bytes can be
//from a single packet
int bytesRead = -1;
while (true) {
//It makes sense for sslStream.Read to block until bytes have been
//read, but it doesn't. Which is why I'm checking if bytesRead!=0
bytesRead = sslStream.Read(buffer, 0, 65536);
if (bytesRead != 0) {
Console.WriteLine(Encoding.UTF8.GetString(buffer, 0, bytesRead));
buffer = new byte[65536];
}
}
}
谢谢大家, 感谢您的帮助
修改
我尝试使用BeginRead和EndRead,因为建议使用“gt”。为此,每当用户发送请求时,我都在使用BeginRead。收到所有数据后,我将它们打印在屏幕上。这似乎工作正常,但我担心将来是否会有任何问题。数据包是否有可能搞砸了?例如,是否有可能EndRead在第一个数据包的末尾没有返回0并且它继续读取第二个数据包?如果可能,我将如何解决这个问题?收到的数据只是http层的主体,因此我无法事先访问IP层以了解数据包的长度。
public void SendData(byte[] message) {
sslStream.Write(message);
sslStream.Flush();
//Start reading for response (if not already reading)
if (sslStream.CanRead) {
sslStream.BeginRead(buffer, 0, BufferSize, ReadData, null);
}
}
void ReadData(IAsyncResult ar) {
int bytesRead = sslStream.EndRead(ar);
if (bytesRead > 0) {
//data may be on their way so start reading again
message.Append(Encoding.UTF8.GetString(buffer, 0, bytesRead));
sslStream.BeginRead(buffer, 0, BufferSize, ReadData, null);
Console.WriteLine("Data received but more may be on their way...");
} else {
//All data arrived (Checking if length is more than 0 since all the
//data may had already arrived in the previous check (above)
if (message.ToString().Length > 0) {
Console.WriteLine(message.ToString());
//Clear StringBuilder and reset buffer.
message.Clear();
buffer = new byte[BufferSize];
}
}
}
再次感谢
答案 0 :(得分:1)
看到while(true)
通常是一个不好的迹象......如果你的代码进入一个没有结束条件的'紧凑'循环,它将继续循环并消耗所有可用资源。
仔细检查'if'条件是否符合您的预期。例如,如果在多个部分中读取流会发生什么? (例如32768的两部分)。这完全有可能。
一旦您对此行为感到满意,您可以使用Read
在尝试下一个Thread.Sleep(100)
之前强制线程稍微休眠一下。
或者,尝试使用BeginRead
查看异步IO。请参阅this example on MSDN。
编辑,回答问题的第2部分:
我怀疑如果出现问题,就会出错,所以代码是防御性的!解决下一个问题的方法是缓冲从流中读取的所有数据。然后让另一个线程尝试从缓冲区读取整个数据包。不要忘记使用锁来防止缓冲区同时被读/写。
为此编写单元测试也是一个好主意,以涵盖“碎片化”行为(以及正常行为)。
或者,您可以查看更高级别的协议,为您处理这些事情。我经常看到的是Google的Protocol Buffers。