【发布时间】:2015-01-30 15:32:31
【问题描述】:
我尝试使用 OpenSSL 创建一个 C++ TLS 客户端,它在 Windows 上使用非阻塞套接字。
我想使用 SSL_read()/SSL_write() 和 select() 函数,但我找不到运行良好的算法,并且网络没有提供好的简单示例。在接收到最后一个数据块后,select() 已经返回超时。
OpenSSL api 看不懂,SSL_pending() 已经返回 0 并选择超时??
选择导致最后一个数据块的关键延迟。
recv_buffer() 的算法是这样的:
我有检查套接字是否可读或可写的函数(运行良好):
int CSocket::socket_RWable(int rw_flag, const int time_out)
{
fd_set rwfs;
int error = 0;
struct timeval timeout;
try
{
memset(&timeout, 0, sizeof(struct timeval));
timeout.tv_sec = time_out;
while( 1 ) // boucle de surveillance
{
FD_ZERO(&rwfs);
FD_SET(m_socket, &rwfs);
// surveiller la socket en lecture ou ecriture
if(rw_flag == R_MODE)
error = select(m_socket+1, &rwfs, NULL, NULL, &timeout);
else if(rw_flag == W_MODE)
error = select(m_socket+1, NULL, &rwfs, NULL, &timeout);
if(error < 0) // echec de select
throw 1;
else if(error == 0) // fin du time out
throw 2;
// Une opération d' entree/sortie sur la socket est disponible
if(FD_ISSET(m_socket, &rwfs) != 0)
{
FD_CLR(m_socket, &rwfs );
return 0;
}
}
}
catch(int ret)
{
FD_CLR(m_socket, &rwfs );
if(ret == 1) throw CErreur("[-] CSocket : select : ", CWinUtil::Win_sys_error(NET_ERROR));
else if(ret == 2) return -1;
}
return -1;
}
更新:
这个函数将数据接收到缓冲区中,并在 las 数据块之后导致超时:
int CTLSClient::recv_buffer(char *buffer, const int buffer_size, const int time_out)
{
int selectErr = 0;
int sslErr = 0;
int retRead = 0;
int recvData = 0;
selectErr = m_socket->socket_RWable(R_MODE, time_out);
while(selectErr == 0)
{
retRead = SSL_read(m_ssl, buffer+recvData, buffer_size-recvData);
sslErr = SSL_get_error(m_ssl, retRead);
if(sslErr == SSL_ERROR_NONE)
{
cout<<"DEBUG 2 SSL_ERROR_NONE recv data="<<retRead<<endl;
recvData += retRead;
}
else if(sslErr == SSL_ERROR_WANT_READ)
{
cout<<"DEBUG 3 SSL_ERROR_WANT_READ select()"<<endl;
selectErr = m_socket->socket_RWable(R_MODE, time_out);
}
else if(sslErr == SSL_ERROR_WANT_WRITE)
{
cout<<"DEBUG 4 SSL_ERROR_WANT_WRITE select()"<<endl;
selectErr = m_socket->socket_RWable(W_MODE, time_out);
}
else if(sslErr == SSL_ERROR_ZERO_RETURN)
{
return -1;
}
else
return -1;
}
return recvData;
}
这是连接到 POP3 服务器的输出:
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
【问题讨论】:
标签: windows sockets openssl nonblocking