首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >SslStream分离线程

SslStream分离线程
EN

Stack Overflow用户
提问于 2013-03-25 14:20:24
回答 1查看 1.7K关注 0票数 1

我试图在屏幕上显示来自ssl流(来自网站)的任何数据。因为我不知道数据何时到达,所以我使用了另一个线程,它一直从流中读取数据直到字节被读取。这是完美的工作,然而,我的CPU使用率跳转到25%,并停留在那里(这是一个线程的最大使用,我的PC有4个线程)。虽然这有点道理,因为线程被困在when循环中,但我没想到thread类的实例会占用整个CPU线程(我敢肯定,在使用简单的Client/Server应用程序时没有发生这种情况)。

当连接初始化后,线程就开始运行,用户可以随时向网站发送数据,应用程序应该打印响应。什么是解决这一问题的替代办法?我应该放弃SslStream并开始使用其他的东西吗?

下面是运行在这个单独线程上的代码:

代码语言:javascript
复制
    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];
            }
        }
    }

谢谢大家,感谢你们的帮助

编辑:

按照"gt“的建议,我尝试使用BeginRead和EndRead。为此,每当用户发送请求时,我都使用BeginRead。当收到所有的数据后,我就把它们打印在屏幕上。这似乎很好,但我担心将来是否会有任何问题。这些包裹有可能被搞砸了吗?例如,是否有可能EndRead在第一个数据包的末尾不返回0,并且继续读取第二个数据包?如果可能的话,我该怎么继续解决这个问题呢?接收到的数据只是http层的主体,所以我不能事先访问IP层来知道数据包的长度。

代码语言:javascript
复制
    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];
            }
        }
    }

再次感谢

EN

回答 1

Stack Overflow用户

回答已采纳

发布于 2013-03-25 14:57:22

看到while(true)通常是个坏兆头..。如果您的代码在没有结束条件的情况下进入“紧密”循环,它将继续循环并消耗它的所有可用资源。

再次检查“if”条件是否符合您的预期。例如,如果流在多个部分中读取,会发生什么情况?(例如32768的两部分)。这是完全可能的。

一旦您对这种行为感到满意,就可以强制线程在尝试下一个Read之前先休眠一段时间,使用Thread.Sleep(100)

或者,尝试使用BeginRead查看异步IO。见在MSDN上的示例

编辑,以回答问题的第2部分:

我怀疑如果某件事可能出错,它就会出错,所以代码是防御性的!下一个问题的解决方案是缓冲从流中读取的所有数据。然后让另一个线程尝试从缓冲区读取整个数据包。不要忘记使用锁来防止同时读取/写入缓冲区。

为此编写单元测试也是个好主意,以涵盖“零散”行为(以及正常行为)。

或者,您可以查看更高级别的协议,该协议为您处理这些问题。我经常提到的一个例子是谷歌的协议缓冲器

票数 1
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/15617256

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档