简体   繁体   English

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

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

I'm writing a simple http server in C, I added some OpenSSL around it to support secure connections and it works great with blocking sockets.我正在用 C 编写一个简单的 http 服务器,我在它周围添加了一些 OpenSSL 以支持安全连接,并且它与阻塞套接字一起工作得很好。

However if I switch to non-blocking sockets, the SSL_accept(ssl) always returns -1 on the first attempt, even if I add a time delay before it.但是,如果我切换到非阻塞套接字,SSL_accept(ssl) 在第一次尝试时总是返回 -1,即使我在它之前添加了一个时间延迟。

I originally assumed it may have something to do with the socket not ready for reads/writes but that doesn't seem to be the case as a delay of even 150ms had the same behavior.我最初认为它可能与未准备好读取/写入的套接字有关,但情况似乎并非如此,因为即使 150 毫秒的延迟也具有相同的行为。

However, if I execute SSL_accept(ssl) then issue a short 50ms delay and retry SSL_accept(ssl), I get a successful SSL connection each time.但是,如果我执行 SSL_accept(ssl) 然后发出 50 毫秒的短暂延迟并重试 SSL_accept(ssl),我每次都会获得成功的 SSL 连接。 Sending and receiving encrypted traffic works just as expected.发送和接收加密流量按预期工作。

I'm not using socket select, I'm simply polling sockets for connect/recv/send.我没有使用套接字选择,我只是轮询套接字以进行连接/接收/发送。

Why is this?为什么是这样? Am I missing a required call for non-blocking accepts?我是否错过了非阻塞接受所需的调用?

Below is the snippet I've added to my code to mitigate this behavior.下面是我添加到我的代码中以减轻这种行为的片段。

    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

From the ssl_accept man page :ssl_accept 手册页

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.如果底层 BIO 是非阻塞的,当底层 BIO 不能满足 SSL_accept() 继续握手的需要时,SSL_accept() 也会返回,通过返回值 -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 .在这种情况下,使用 SSL_accept() 的返回值调用 SSL_get_error() 将产生 SSL_ERROR_WANT_READ 或 SSL_ERROR_WANT_WRITE 。 The calling process then must repeat the call after taking appropriate action to satisfy the needs of SSL_accept().然后,调用过程必须在采取适当的操作以满足 SSL_accept() 的需要后重复调用。 The action depends on the underlying BIO .该操作取决于底层 BIO 。 When using a non-blocking socket, nothing is to be done, but select() can be used to check for the required condition.使用非阻塞套接字时,无需执行任何操作,但可以使用 select() 检查所需条件。 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.使用缓冲 BIO 时,如 BIO 对,数据必须在能够继续之前写入或检索出 BIO。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM