来自多个线程的OpenSSL SSL_read和SSL_write

时间:2014-08-19 20:34:35

标签: multithreading ssl openssl

我知道在OpenSSL API中禁止从同一SSL_read上下文中的两个不同线程调用SSL_writeSSL,但在我的应用程序中保持安全 - 双工通信。我想到了一些解决方案,我都不喜欢这些解决方案:

  1. 每个连接使用两个SSL个上下文。我不喜欢这样,因为它使用了更多的资源,这会使我的实现变得复杂。但是,如果我可以“复制”现有的SSL上下文而不是从头开始创建一个全新的连接,我会很好用。
  2. 使用非阻塞套接字和互斥锁控制对SSL上下文的访问。这需要资源占用轮询,我听说非阻塞实现不是很好。
  3. 这似乎是一件相当普遍的事情,那么这个问题的解决方案是什么?

1 个答案:

答案 0 :(得分:2)

  

使用非阻塞套接字和互斥锁控制对SSL上下文的访问。

在单个线程中使用非阻塞套接字,您不需要互斥锁,因为您只需要读取或写入(因为单个线程)。

  

这需要资源占用轮询,......

您不需要“资源占用”轮询。我假设你的意思是繁忙的轮询,而不是使用系统的常用设施(如select)等待(不循环),直到数据可用或数据可以发送。但与普通套接字上的读/写相反,SSL套接字如果要写,则需要读取,如果要读取则需要写入,即使套接字不可读,它们也可能包含数据。请注意SSL_WANT_READSSL_WANT_WRITESSL_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对象)。