2

我想知道使用 AcceptEx 和 OpenSSL 处理来自客户端的新连接的正确方法。我有一个非常好的工作服务器,它通过常规 HTTP 使用带有 IO 完成端口的 AcceptEx。我想为其添加 OpenSSL 支持。

我在互联网上阅读了几篇关于将 OpenSSL 与非阻塞套接字一起使用的文章:

他们似乎都没有涉及如何做到这一点,因为他们主要关心连接的客户端。AcceptEx 建立套接字连接并向您返回从客户端发送的第一条数据。我发布的第一个链接讨论了如何使用 IOCP 处理传入数据。到目前为止,我已经尝试过在那里发布的内容,但没有任何运气。基本上我在服务器上看到的内容如下:

  1. 接收到接受的连接完成。
  2. 我使用 SSL_new(ctx) 创建 SSL 对象
  3. 我用 BIO_new(BIO_s_mem()) 创建了输入和输出 BIO 对象。
  4. 我通过调用 SSL_set_bio(ssl, bioIn, bioOut) 在 SSL 对象中设置 BIO。
  5. 我调用 SSL_set_accept_state(ssl) 以允许 SSL_read 和 SSL_write 进行协商。

然后我继续尝试处理 AcceptEx 调用读取的第一个数据缓冲区。

  1. 我调用 BIO_Write(bioIn, buf, len) 将读取的数据复制到 SSL 中。
  2. 然后,我检查 bioOut 上的待处理握手数据,看看是否需要将其发送回客户端。不过,在接受新连接时,我从未见过 bioOut 中有任何数据。
  3. 然后我调用 SSL_read(ssl, plainTextBuf, len) 来尝试解密我在第 6 步中放入 bioIn 的数据。这总是返回 -1,而 SSL_get_error 返回 ERROR_SSL_WANT_READ。据我了解,这意味着 bioIn 没有完整的 SSL 记录,因此 SSL 需要来自客户端的更多数据才能解密任何内容。

这是我开始遇到问题的地方,也是我认为我需要一些指导的地方。我已经尝试了很多东西。如果我此时重复调用 SSL_read,它将无限返回 ERROR_SSL_WANT_READ,大概是因为使用内存 BIO 实际上并没有通过套接字进行通信以接收更多数据。我应该发布 WSARecv 调用以等待来自客户端的更多数据吗?

此时我还尝试使用 BIO_read 检查 bioOut 缓冲区,以查看是否有数据需要发送回客户端。确实有一些,我使用 WSASend 将其发回,并发布另一个 WSARecv 调用以等待更多数据(以响应我的发送)。这导致从客户端接收更多数据(WSARecv 在发送完成后完成),因此看起来好像连接正在进行中。但是,当我处理完成的读取时,SSL_read 和 BIO_read 都返回 ERROR_SSL_WANT_READ。所以,我没有足够的数据来解密完整的记录,也没有什么可以发回给客户。发布另一个 WSARecv 调用以响应这种情况也不会从客户端接收更多数据。我不知道 SSL 在这里想要什么。

我现在卡住了,但我会继续尝试更多的东西。如果我发现任何问题,我会用评论更新这个问题。

4

1 回答 1

3

您在套接字上发出一个新的重叠读取,等待它完成,将数据推送到您的 BIO 并循环执行您当前正在执行的步骤。

ERROR_SSL_WANT_READ意味着 BIO 需要更多数据,即它需要再次读取。

在数据流期间的任何时候,您可能需要允许 SSL 层发送或接收更多数据,然后才能将更多应用程序级数据推送到 BIO。

我认为我在您引用的文章中非常清楚地涵盖了所有这些;那篇文章中的代码是我在自己的基于 IOCP 的服务器中使用的代码的基础......

于 2011-12-17T21:50:43.623 回答