2012-04-24 24 views
6

我有一個TCP網絡庫,它實現了一堆協議(redis,http等),它們使用BSD套接字實現。將SSL集成到使用BSD套接字的程序中

很多代碼使用select()和其他BSD套接字函數。我是否認爲這不適用於SSL套接字?或者他們會按原樣工作?

我只是想知道,如果SSL和BSD套接字是如此不同,他們需要一個完全不同的方法來實現。

+1

SSL通信使用普通的「BSD」套接字,它只是另一種協議級別,例如, TCP。 – 2012-04-24 08:06:58

回答

6

假設你指的是OpenSSL,它位於套接字之上,它不會取代它。所以所有的直接插座操作,如select(),仍然有效。但是,不同之處在於OpenSSL爲您處理讀寫操作,因此您可以用ssl_read()send()替換recv()ssl_write(),但您可以(並且在某些情況下仍需要)仍然可以直接使用select()。然而,你不能隨便調用它,你必須等到OpenSSL告訴你調用它。因此,例如,如果您有一個讀取循環,首先調用select(),然後僅在select()報告可讀性時調用recv(),則必須交換該邏輯。呼叫ssl_read()第一,然後調用select()只有ssl_read()返回或者SSL_ERROR_WANT_READSSL_ERROR_WANT_WRITE(注意ssl_read()可以在內部進行寫入操作,並ssl_write()可以進行內部讀取操作)。

2

想到的一件事是,你不應該在通過其運行ssl連接的fd上進行選擇。這是因爲它可能例如說你可以在ssl_read被阻塞時讀取它。然後,這例如由SSL進行關鍵重新談判而不是應用數據變得可用。這是一個祕密。

+1

實際上,仍然使用select(),但協議邏輯應檢查不選擇(),但在緩衝區中解碼數據的可用性。 – 2012-04-24 08:34:50

0

這可能會很晚,但可能會爲未來用戶提供很好的參考。在url http://developerweb.net/viewtopic.php?id=6824上使用select()函數有一個很好的線程。舉一個例子是僅在執行SSL_read()SSL_write()後如下

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); 
} 

這是。