【问题标题】:How to set SSL_connect on non blocking socket with select on linux platform如何在 Linux 平台上使用 select 在非阻塞套接字上设置 SSL_connect
【发布时间】:2013-08-08 13:15:11
【问题描述】:

我正在尝试使用 select 函数来实现从客户端到服务器的非阻塞连接。我找到了一个包含一些代码的教程并尝试适应这一点:

...
sockfd = socket(AF_INET, SOCK_STREAM, 0);
err = connect(sockfd,(struct sockaddr*)&sa,sizeof(sa));
...
SSL_set_fd(pssl,sockfd);
err = SSL_connect_nonb(pssl,sockfd,60);
if(err <=0 ){
    printf("SSL_connect:%s\n",ERR_error_string(SSL_get_error(pssl,err),NULL));
    return -1;
}
...

SSL_connect_nonb 函数定义如下:

int SSL_connect_nonb(SSL*pssl,int sockfd, int nsec)
{
    int flags, error;
    socklen_t len;
    fd_set rset, wset;
    struct timeval tval;
    flags = fcntl(sockfd, F_GETFL, 0);
    fcntl(sockfd, F_SETFL, flags | O_NONBLOCK);
    int err = SSL_connect(pssl);
    int err2 = SSL_get_error(pssl,err);
    switch(err2) {
            default:
                printf("SSL_connect err=%s\n",ERR_error_string(err2,0));
                return -1;
                break;
            case SSL_ERROR_WANT_READ:
            case SSL_ERROR_WANT_WRITE:
                break;
    }
    FD_ZERO(&rset);
    FD_ZERO(&wset);
    FD_SET(sockfd, &rset);
    FD_SET(sockfd, &wset);
    tval.tv_sec = nsec;
    tval.tv_usec = 0;
    if (select(sockfd+1, &rset, &wset, NULL,nsec ? &tval:NULL) == 0) {
        return -1;
    }
    if(FD_ISSET(sockfd,&rset) || FD_ISSET(sockfd, &wset )) {
        len = sizeof(error);
        if(getsockopt(sockfd, SOL_SOCKET, SO_ERROR, &error, &len) < 0){
            return -1;
        }
    }else{
        printf("sockfd  not set\n");
        return -1;
    }
    fcntl(sockfd, F_SETFL, flags);
    if (error) {
        return -1;
    }
    return 1;
}

sockfd用connect是正确的,问题是在SSL_connect_nonb中select函数返回avalue=1(实际上条件FD_ISSET(sockfd, &wset)一直都是成功的),但是如果我这样使用阻塞方法:

....    
SSL_set_fd(pssl,sockfd);
err = SSL_connect(pssl);
if(err <=0 ){
    printf("SSL_connect:%s\n",ERR_error_string(SSL_get_error(pssl,err),NULL));
    return -1;
}
...

由于SSL_connect不成功,err的值为0,那么,如何通过调用select函数在非阻塞套接字上进行SSL_connect呢?

【问题讨论】:

    标签: select ssl openssl connect


    【解决方案1】:

    SSL_connect(),又称 SSL 客户端握手,是一个复杂的过程,需要与服务器进行多次往返。因此,当您在非阻塞套接字上运行SSL_connect() 时,仅运行一次是不够的。当您收到SSL_ERROR_WANT_READSSL_ERROR_WANT_WRITE 时,您必须再次重试SSL_connect(),直到它成功或失败并出现其他错误。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2012-11-13
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2010-10-29
      • 2013-06-03
      • 2013-07-20
      相关资源
      最近更新 更多