OpenSSL 多线程读/写

Posted

技术标签:

【中文标题】OpenSSL 多线程读/写【英文标题】:OpenSSL multithreaded read/write 【发布时间】:2016-02-23 08:52:37 【问题描述】:

我目前正在使用 OpenSSL 编写客户端。理想情况下,客户拥有例如4个线程等待从服务器读取,当一个线程读取时,它可能会执行一些工作,然后写入服务器并返回队列以从服务器读取。

OpenSSL 文档指出我不能在不同的线程中使用 SSL_read()SSL_write()。然而SSL_read()是一个阻塞调用,我不能SSL_write()直到它返回?我知道我可以使用select 并执行非阻塞SSL_read(),但我发现这个解决方案不太理想。

OpenSSL 声明SSL_write() 可以返回SSL_ERROR_WANT_READ,从而使问题进一步复杂化。如果所有线程都想写,那么这将导致死锁。

我的问题是:如果我要在 SSL 连接上使用单独的输入和输出 BIO,是否可以在另一个线程写入输出 BIO 时从输入 BIO 进行阻塞读取?

欢迎任何其他建议,我还查看了 gnutls,它支持从多个线程对同一会话进行写入和读取。

【问题讨论】:

连接不是多线程的。如果您需要四个线程,则需要四个连接,除非您可以自己在它们之间进行仲裁和顺序化。 SSL_read() 是一个阻塞调用意味着它阻塞,而不是你不能同时调用其他函数。因此,您关于死锁的陈述也是不合逻辑的。不清楚您在问什么。 如果我想在等待阻塞 SSL_read() 完成的同时使用 SSL_write(),这可能需要很长时间。 你从哪里得到的?如果正在进行握手,则接收和发送写入都将解除阻塞并返回适当的状态代码,如果不是,则发送可以与接收同时进行。 如文档所述,不能同时调用 SSL_read 和 SSL_write。因此,如果我需要从一个线程调用 SSL_read(),则不允许从另一个线程调用 SSL_write(),导致应用程序挂起。 所以你需要四个连接,正如我最初所说的那样。 【参考方案1】:

目前尚不清楚为什么您说将 select 与非阻塞套接字一起使用对您来说不是最佳解决方案。

OpenSSL 不允许 SSL_read 和 SSL_write 同时发生,因为握手可以由于重新协商请求而被触发,并且握手状态不能跨线程共享。同样,非阻塞或其他错误信息存储在每个会话的单个变量中,当您在多个线程中使用相同的会话/连接时,可能会发生争用情况。在我的建议中,最好在单线程中完成与一个 SSL 连接/会话相关的所有操作。如果您有多个连接,则可以生成线程来处理不同线程上的不同连接。

【讨论】:

以上是关于OpenSSL 多线程读/写的主要内容,如果未能解决你的问题,请参考以下文章

C++11 中的读/写多线程

利用requestbeautifulsoupxml写多线程爬虫

Java多线程——锁概念与锁优化

图文多线程入门教程

OpenSSL C多线程客户端分段故障

多线程中的锁机制