我知道在OpenSSL API中禁止从同一SSL_read
上下文中的两个不同线程调用SSL_write
和SSL
,但在我的应用程序中保持安全 - 双工通信。我想到了一些解决方案,我都不喜欢这些解决方案:
SSL
个上下文。我不喜欢这样,因为它使用了更多的资源,这会使我的实现变得复杂。但是,如果我可以“复制”现有的SSL
上下文而不是从头开始创建一个全新的连接,我会很好用。SSL
上下文的访问。这需要资源占用轮询,我听说非阻塞实现不是很好。这似乎是一件相当普遍的事情,那么这个问题的解决方案是什么?
答案 0 :(得分:2)
使用非阻塞套接字和互斥锁控制对SSL上下文的访问。
在单个线程中使用非阻塞套接字,您不需要互斥锁,因为您只需要读取或写入(因为单个线程)。
这需要资源占用轮询,......
您不需要“资源占用”轮询。我假设你的意思是繁忙的轮询,而不是使用系统的常用设施(如select
)等待(不循环),直到数据可用或数据可以发送。但与普通套接字上的读/写相反,SSL套接字如果要写,则需要读取,如果要读取则需要写入,即使套接字不可读,它们也可能包含数据。请注意SSL_WANT_READ
,SSL_WANT_WRITE
和SSL_pending
。
......我听说非阻塞实现不是很好。
如果您习惯使用线程,它看起来会更复杂。但你有没有想过为什么像nginx这样的高性能服务器不使用线程而是使用非阻塞I / O?这是因为它需要更少的资源并且没有与线程相关的问题,例如需要在关键部分(开销)周围进行互操作,并在忘记互斥时遇到奇怪和零星的错误。 nginx还使用openssl和非阻塞I / O.
我个人一直使用非阻塞I / O,虽然由于协议本身而不是OpenSSL实现,因此很难正确地使用SSL,但它是可行且快速的。
这意味着,单个线程中的非阻塞I / O是您解决问题的一种方式。另一种方法是让SSL只与内存BIO一起使用而不是真正的文件描述符,并自己完成所有的读写操作。但这可能比非阻塞I / O更复杂。
BTW,通常 SSL上下文表示可以在多个SSL连接之间共享的SSL_CTX
对象,并且多个线程可能没有问题。你的意思是不应该从多个线程使用相同的 SSL连接(SSL
对象)。