SSL_read因SSL_ERROR_WANT_READ阻塞后必须要等SSL_read完成才可以继续调用SSL_write吗?

我现在项目需要将SSL阻塞方式改为非阻塞方式,使用的多线程,在一个线程中对一个SSL对象SSL_write,在另一个线程中使用该对象进行SSL_read操作。

《Network Security with OpenSSL》讲non-blocking的一节中有个data_transfer的示例程序:

for (;;)
{
    /* check_availability使用I/O复用接口(select、poll、epoll等)来获取socket是否可读或可写 */
    check_availability(A, &can_read_A, &can_write_A, B, &can_read_B, &can_write_B);

    /* write_waiton_read_A:调用SSL_write时因SSL_ERROR_WANT_READ阻塞
     * write_waiton_write_A:调用SSL_write时因SSL_ERROR_WANT_WRITE阻塞
     * read_waiton_write_A:调用SSL_read时因SSL_ERROR_WANT_WRITE阻塞
     * read_waiton_read_A:调用SSL_read时因SSL_ERROR_WANT_READ阻塞
     */
     
    if (!(write_waiton_read_A || write_waiton_write_A) && // A的write没有完成
            (A2B_len != BUF_SIZE) &&
            /* A可读,或者之前read因WANT_WRITE阻塞而此时A可写 */
            (can_read_A || (can_write_A && read_waiton_write_A)))
    {
        read_waiton_read_A = 0;
        read_waiton_write_A = 0;

        code = SSL_read(A, A2B + A2B_len, BUF_SIZE - A2B_len);
        switch (SSL_get_error(A, code))
        {
            ...
        case SSL_ERROR_WANT_READ:
            read_waiton_read_A = 1;
            break;
            
         case SSL_ERROR_WANT_WRITE:
             read_waiton_write_A = 1;
             break;
            ...
        }
    }
    
    ...

    if (!(read_waiton_write_A || read_waiton_read_A) &&
        have_data_B2A &&
        /* A可写,或者write因WANT_READ阻塞而此时A可读 */
        (can_write_A || (can_read_A && write_waiton_read_A)))
    {
        write_waiton_read_A = 0;
        write_waiton_write_A = 0;

        code = SSL_write(A, B2A, B2A_len);
        switch (SSL_get_error(A, code))
        {
            ...
        case SSL_ERROR_WANT_READ:
            write_waiton_read_A = 1;
            break;
            
        case SSL_ERROR_WANT_WRITE:
            write_waiton_write_A = 1;
            ...
        }
    }

    ...
}

上面的代码中,如果A之前的SSL_read因SSL_ERROR_WANT_READ未完成,则需等SSL_read完成才能对A进行SSL_write(就算A此时可写)。

我程序中的连接在发送时同时需要接收,请问如果一个SSL对象的操作(比如SSL_read)阻塞(比如因SSL_ERROR_WANT_READ)后,必须等该操作完成后才能调用另外一个对应的操作(比如SSL_write)吗?

阅读 16k
1 个回答

应该是的,由于重协商的存在,SSL_write也会产生SSL_ERROR_WANT_READ。如果你不处理完SSL_read,后面发生可读事件时,怎么知道要调用SSL_write还是SSL_read?

撰写回答
你尚未登录,登录后可以
  • 和开发者交流问题的细节
  • 关注并接收问题和回答的更新提醒
  • 参与内容的编辑和改进,让解决方法与时俱进