如何正确使用SSL_read()和select()? 我尝试用OpenSSL在Windows上使用一个非阻塞套接字来制作一个C++ TLS客户端。p>

如何正确使用SSL_read()和select()? 我尝试用OpenSSL在Windows上使用一个非阻塞套接字来制作一个C++ TLS客户端。p>,windows,sockets,openssl,nonblocking,Windows,Sockets,Openssl,Nonblocking,我想使用SSL_read()/SSL_write()和select()函数,但我没有找到运行良好的算法,网络也没有提供好的简单示例。接收到最后一块数据后,select()返回一个超时 我不理解OpenSSL api,SSL_pending()返回0并选择超时 选择“导致最后一组数据的临界延迟” 我的recv_buffer()算法如下: 我有一个功能,可以检查套接字是否可读写(工作正常): 假设您已经读取了标题,由于某种原因,SSL_read()在读取电子邮件后挂起并返回SSL_WANT_read

我想使用SSL_read()/SSL_write()和select()函数,但我没有找到运行良好的算法,网络也没有提供好的简单示例。接收到最后一块数据后,select()返回一个超时

我不理解OpenSSL api,SSL_pending()返回0并选择超时

选择“导致最后一组数据的临界延迟”

我的recv_buffer()算法如下:

我有一个功能,可以检查套接字是否可读写(工作正常):


假设您已经读取了标题,由于某种原因,SSL_read()在读取电子邮件后挂起并返回SSL_WANT_read。我解决了这个问题,通过在消息体中一行一行地循环,直到找到结束周期。当我到达这一行时,我调用SSL_pending()。虽然没有挂起的数据,但它可以防止SSL\u read()返回SSL\u WANT\u read的无休止循环。然而,我正在寻找更好的解决方案

for(;;)
{
    char *line = ReadLine(ssl, buf, sizeof(buf));
    if(line != NULL)
    {
        if(*line == '.')
        {
            int pending = SSL_pending(ssl);
            if(pending > 0)
            {
                int read = SSL_read(ssl,buf,pending);
            }
        }
    }
}
此函数每次读取一个字符,直到到达行尾字符并返回行

char *ReadLine(SSL *ssl, char *buf, int size)
{
    int i = 0;
    char *ptr = NULL;
    for (ptr = str; size > 1; size--, ptr++)
    {
        i = SSL_read(out, ptr, 1);
        switch (SSL_get_error(out, i)){
        case SSL_ERROR_NONE:
            break;
        case SSL_ERROR_ZERO_RETURN:
            break;
        case SSL_ERROR_WANT_READ:
            break;
        case SSL_ERROR_WANT_WRITE:
            break;
        default:
            TRACE("SSL problem\r\n");
        }

        if (*ptr == '\n')
            break;   
        if (*ptr == '\r'){
            ptr--;
        }
    }


    *ptr = '\0';

    return(str);
}
DEBUG 2  SSL_ERROR_NONE recv data=35
DEBUG 3  SSL_ERROR_WANT_READ select()
[S]+OK BLU0-POP617 POP3 server ready
total data -> 35
DEBUG 2  SSL_ERROR_NONE recv data=23
DEBUG 3  SSL_ERROR_WANT_READ select()
[S]+OK password required
total data -> 23
DEBUG 2  SSL_ERROR_NONE recv data=30
DEBUG 3  SSL_ERROR_WANT_READ select()
[S]+OK mailbox has 180 messages
total data -> 30
DEBUG 2  SSL_ERROR_NONE recv data=18
DEBUG 3  SSL_ERROR_WANT_READ select()
[S]+OK 180 12374432
total data -> 18
DEBUG 2  SSL_ERROR_NONE recv data=13
DEBUG 3  SSL_ERROR_WANT_READ select()
[S]+OK 1 23899
total data -> 13
DEBUG 2  SSL_ERROR_NONE recv data=5
DEBUG 3  SSL_ERROR_WANT_READ select()
DEBUG 2  SSL_ERROR_NONE recv data=8192
DEBUG 2  SSL_ERROR_NONE recv data=8192
DEBUG 3  SSL_ERROR_WANT_READ select()
DEBUG 3  SSL_ERROR_WANT_READ select()
DEBUG 2  SSL_ERROR_NONE recv data=7521
DEBUG 3  SSL_ERROR_WANT_READ select()
[S]total data -> 23910
for(;;)
{
    char *line = ReadLine(ssl, buf, sizeof(buf));
    if(line != NULL)
    {
        if(*line == '.')
        {
            int pending = SSL_pending(ssl);
            if(pending > 0)
            {
                int read = SSL_read(ssl,buf,pending);
            }
        }
    }
}
char *ReadLine(SSL *ssl, char *buf, int size)
{
    int i = 0;
    char *ptr = NULL;
    for (ptr = str; size > 1; size--, ptr++)
    {
        i = SSL_read(out, ptr, 1);
        switch (SSL_get_error(out, i)){
        case SSL_ERROR_NONE:
            break;
        case SSL_ERROR_ZERO_RETURN:
            break;
        case SSL_ERROR_WANT_READ:
            break;
        case SSL_ERROR_WANT_WRITE:
            break;
        default:
            TRACE("SSL problem\r\n");
        }

        if (*ptr == '\n')
            break;   
        if (*ptr == '\r'){
            ptr--;
        }
    }


    *ptr = '\0';

    return(str);
}