SslStream分离线程

时间:2013-03-25 14:20:25

标签: c# multithreading sslstream

我正在尝试在屏幕上显示来自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];
            }
        }
    }

再次感谢

1 个答案:

答案 0 :(得分:1)

看到while(true)通常是一个不好的迹象......如果你的代码进入一个没有结束条件的'紧凑'循环,它将继续循环并消耗所有可用资源。

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

一旦您对此行为感到满意,您可以使用Read在尝试下一个Thread.Sleep(100)之前强制线程稍微休眠一下。

或者,尝试使用BeginRead查看异步IO。请参阅this example on MSDN


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

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

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

或者,您可以查看更高级别的协议,为您处理这些事情。我经常看到的是Google的Protocol Buffers