【发布时间】:2014-06-07 14:33:06
【问题描述】:
我创建了一个常规的 C 套接字。连接后,它按预期返回EWOULDBLOCK/WSAEWOULDBLOCK,因为我这样做了:
unsigned long int mode = 0;
ioctlsocket(ssl_info->sock, FIONBIO, &mode);
setsockopt(ssl_info->sock, SOL_SOCKET, SO_RCVTIMEO, (char*)&tv, sizeof(tv));
setsockopt(ssl_info->sock, SOL_SOCKET, SO_SNDTIMEO, (char*)&tv, sizeof(tv));
将套接字置于非阻塞模式。之后我会这样做:
ssl = SSL_new(ctx);
SSL_set_fd(ssl, sock);
return SSL_connect(ssl);
但是,它返回 -1。
我在网上看到这意味着我需要处理SSL_ERROR_WANT_READ和SSL_ERROR_WANT_WRITE。
所以我做到了:
int res = -1;
while(res == -1)
{
res = SSL_connect(ssl);
switch (SSL_get_error(ssl, res))
{
case SSL_ERROR_WANT_CONNECT:
MessageBox(NULL, "Connect Error", "", 0);
break;
case SSL_ERROR_WANT_READ: //prints this every time..
MessageBox(NULL, "Read Error", "", 0);
break;
case SSL_ERROR_WANT_WRITE:
MessageBox(NULL, "Write Error", "", 0);
break;
}
SelectSocket(ssl);
}
std::cout<<"Connected!\n";
其中SelectSocket定义为:
bool SelectSocket(SSL* ssl)
{
if (blockmode)
{
fd_set readfds;
fd_set writefds;
FD_ZERO(&readfds);
FD_ZERO (&writefds);
FD_SET(ssl_info->sock, &readfds);
FD_SET(ssl_info->sock, &writefds);
struct timeval tv = {0};
tv.tv_sec = timeout / 1000;
tv.tv_usec = timeout % 1000;
return select(sock + 1, &readfds, &writefds, NULL, &tv) >= 0;
}
return select(sock + 1, NULL, NULL, NULL, NULL) != SOCKET_ERROR;
}
那么我究竟怎样才能让它连接起来呢?当套接字非阻塞时,我似乎无法读取或写入任何内容:S.
有什么想法吗?
【问题讨论】:
-
在非阻塞套接字上设置发送或接收超时没有意义。您确实需要处理 WANT_READ 和 WANT_WRITE。我建议你这样做。
-
您的函数 SelectSocket 返回 bool,但您将其与 -1 进行比较 - 这可能不太好
-
好的,我修复了
-1的问题。还是一样。我不确定处理WANT_READ和WANT_WRITE的文档意味着什么。我尝试在无限循环中执行SSL_read;没有区别。 -
@Brandon,您提到 SSL_connect() 返回 (-1)。我假设您的代码随后称为 SSL_get_error()? (我在提供的代码中没有看到)。如果是,SSL_get_error() 返回了什么?
-
我将代码添加到 OP。