我有一個TCP網絡庫,它實現了一堆協議(redis,http等),它們使用BSD套接字實現。將SSL集成到使用BSD套接字的程序中
很多代碼使用select()和其他BSD套接字函數。我是否認爲這不適用於SSL套接字?或者他們會按原樣工作?
我只是想知道,如果SSL和BSD套接字是如此不同,他們需要一個完全不同的方法來實現。
我有一個TCP網絡庫,它實現了一堆協議(redis,http等),它們使用BSD套接字實現。將SSL集成到使用BSD套接字的程序中
很多代碼使用select()和其他BSD套接字函數。我是否認爲這不適用於SSL套接字?或者他們會按原樣工作?
我只是想知道,如果SSL和BSD套接字是如此不同,他們需要一個完全不同的方法來實現。
假設你指的是OpenSSL,它位於套接字之上,它不會取代它。所以所有的直接插座操作,如select()
,仍然有效。但是,不同之處在於OpenSSL爲您處理讀寫操作,因此您可以用ssl_read()
和send()
替換recv()
和ssl_write()
,但您可以(並且在某些情況下仍需要)仍然可以直接使用select()
。然而,你不能隨便調用它,你必須等到OpenSSL告訴你調用它。因此,例如,如果您有一個讀取循環,首先調用select()
,然後僅在select()
報告可讀性時調用recv()
,則必須交換該邏輯。呼叫ssl_read()
第一,然後調用select
()只有ssl_read()
返回或者SSL_ERROR_WANT_READ
或SSL_ERROR_WANT_WRITE
(注意ssl_read()
可以在內部進行寫入操作,並ssl_write()
可以進行內部讀取操作)。
想到的一件事是,你不應該在通過其運行ssl連接的fd上進行選擇。這是因爲它可能例如說你可以在ssl_read被阻塞時讀取它。然後,這例如由SSL進行關鍵重新談判而不是應用數據變得可用。這是一個祕密。
實際上,仍然使用select(),但協議邏輯應檢查不選擇(),但在緩衝區中解碼數據的可用性。 – 2012-04-24 08:34:50
這可能會很晚,但可能會爲未來用戶提供很好的參考。在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);
}
這是。
SSL通信使用普通的「BSD」套接字,它只是另一種協議級別,例如, TCP。 – 2012-04-24 08:06:58