7

我有一个 TCP 网络库,它实现了一堆协议(redis、http 等),它们是使用 BSD 套接字实现的。

许多代码使用 select() 和其他用于 BSD 套接字的函数。我是否正确假设这不适用于 SSL 套接字?还是他们会按原样工作?

我只是想知道 SSL 和 BSD 套接字是否如此不同以至于它们需要完全不同的实现方法。

4

3 回答 3

7

假设您指的是 OpenSSL,它位于套接字的顶部,不会取代它。因此,所有直接套接字操作,如select(),仍然有效。但是,不同之处在于 OpenSSL 为您处理读取和写入,因此您可以替换recv()ssl_read()send()ssl_write()但您仍然可以(并且在某些情况下需要)select()直接使用。但是,您不能随时调用它,您必须等到 OpenSSL 告诉您调用它。因此,例如,如果您有一个读取循环select()首先调用,然后recv()仅在select()报告可读性时调用,您将不得不交换该逻辑。先调用ssl_read(),再调用select() 仅当ssl_read()返回SSL_ERROR_WANT_READ或时SSL_ERROR_WANT_WRITE(注意ssl_read()可以在内部进行写操作,也ssl_write()可以在内部进行读操作)。

于 2012-04-24T19:31:46.360 回答
2

想到的一件事是,您不应该在运行 ssl 连接的 fd 上进行选择。那是因为它可能会说你可以在 ssl_read 阻塞时读取它。例如,这是由于 SSL 进行密钥重新协商而不是应用程序数据变得可用而导致的。这就是陷阱之一。

于 2012-04-24T08:12:14.760 回答
0

这可能会迟到,但可能会为未来的用户提供很好的参考。在 url http://developerweb.net/viewtopic.php?id=6824上使用 select() 函数有一个很好的线程。引用的一个例子如下

int sslsock_handle_nbio (ssl, ret, totv)
    void            *ssl;           /* -> the SSL info                      */
    int             ret;            /* the SSL I/O function return value    */
    struct timeval  *totv;          /* -> timeout info, or NULL             */
{
    int     sfd, i;
    fd_set  rset, wset;

    sfd = SSL_get_fd (ssl);
    i = SSL_get_error (ssl, ret);

    if (i == SSL_ERROR_WANT_READ) {
    do {
        FD_ZERO (&rset);
        FD_SET (sfd, &rset);
        i = select (sfd + 1, &rset, NULL, NULL, totv);
    } while ((i < 0) && (errno == EINTR));
    if (i == 0) {
        /* the select() timed out */
        ret = -2;
        errno = ETIMEDOUT;
    } else {
        /* either an error, or it's readable */
        ret = i;
    }
    } else if (i == SSL_ERROR_WANT_WRITE) {
    do {
        FD_ZERO (&wset);
        FD_SET (sfd, &wset);
        i = select (sfd + 1, NULL, &wset, NULL, totv);
    } while ((i < 0) && (errno == EINTR));
    if (i == 0) {
        /* the select() timed out */
        ret = -2;
        errno = ETIMEDOUT;
    } else {
        /* either an error, or it's writable */
        ret = i;
    }
    }
    /* else, leave "ret" alone, and return it as-is */

    return (ret);
}

这仅在执行SSL_read()or之后SSL_write()

于 2014-06-23T00:44:37.367 回答