尝试接受非阻塞 OpenSSL 套接字时出现错误 -1。延迟接受两次有效

Error -1 when attempting to accept a non-blocking OpenSSL socket. Accepting twice with a delay works

我正在用 C 编写一个简单的 http 服务器,我在它周围添加了一些 OpenSSL 以支持安全连接,并且它非常适合阻塞套接字。

但是,如果我切换到非阻塞套接字,SSL_accept(ssl) 在第一次尝试时总是 returns -1,即使我在它之前添加了时间延迟。

我最初认为它可能与尚未为 reads/writes 准备好的套接字有关,但事实似乎并非如此,因为即使延迟 150 毫秒也有相同的行为。

但是,如果我执行 SSL_accept(ssl) 然后发出一个短暂的 50 毫秒延迟并重试 SSL_accept(ssl),我每次都能成功建立 SSL 连接。发送和接收加密流量按预期工作。

我没有使用套接字 select,我只是在轮询 connect/recv/send.

的套接字

这是为什么?我是否错过了非阻塞接受所需的调用?

下面是我添加到我的代码中以减轻这种行为的片段。

    int sslfail = SSL_accept(ssl);
    #if NONBLOCKINGIO
    // Perculiar issue where non-blocking sockets require 2 accept attempts with a brief delay betweek them to avoid error.
    usleep(50 * 1000);
    sslfail = SSL_accept(ssl);
    #endif

来自ssl_accept man page

If the underlying BIO is non-blocking, SSL_accept() will also return when the underlying BIO could not satisfy the needs of SSL_accept() to continue the handshake, indicating the problem by the return value -1. In this case a call to SSL_get_error() with the return value of SSL_accept() will yield SSL_ERROR_WANT_READ or SSL_ERROR_WANT_WRITE . The calling process then must repeat the call after taking appropriate action to satisfy the needs of SSL_accept(). The action depends on the underlying BIO . When using a non-blocking socket, nothing is to be done, but select() can be used to check for the required condition. When using a buffering BIO , like a BIO pair, data must be written into or retrieved out of the BIO before being able to continue.