openssl - AcceptEx 和 OpenSSL

标签 openssl iocp

我想知道使用 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 调用读取的第一个数据缓冲区。

  • 我调用 BIO_Write(bioIn, buf, len) 将读取的数据复制到 SSL 中。
  • 然后,我检查 bioOut 上待处理的握手数据,看看是否需要将其发送回客户端。不过,当接受新连接时,我目前还没有看到 bioOut 中有任何数据。
  • 然后,我调用 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 想要什么。

    我现在陷入困境,但我会继续尝试更多的事情。如果我发现任何问题,我会用评论更新这个问题。

    最佳答案

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

    ERROR_SSL_WANT_READ 表示 BIO 需要更多数据,即它需要再次读取。

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

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

    关于openssl - AcceptEx 和 OpenSSL,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/8510731/

    相关文章:

    c++ - fatal error : openssl/ssl. h:没有这样的文件或目录

    openssl - 使用静态链接构建 libcurl 到 openssl

    ruby-on-rails - 如何重新编译 Ruby 和 OpenSSL?

    c++ - 使用基于 IOCP 的客户端的每个 IO 数据

    c++ - 如何使用 WSASend() 和 IOCP 模拟阻塞 send()?

    multithreading - libuv 与原始 epoll 或 IOCP

    linux - 这是公共(public)/ key 登录的良好设置吗?

    linux - openssl 未知选项错误

    windows - 有什么方法可以使用 IOCP 通知套接字何时可读/可写?

    c++ - 从 IOCP 线程调用 WSAGetLastError() 返回不正确的结果