非阻塞连接OpenSSL

我创建了一个普通的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_READSSL_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。

有任何想法吗?

SSL_connect()返回的(-1)表示底层BIO无法满足SSL_connect()的需要以继续握手。

通常,调用进程必须在采取适当的操作以满足SSL_connect()的需要后重复调用。

但是,当使用非阻塞套接字时,不需要做任何事情; 但select()可用于检查所需的条件。

(当使用缓冲BIO时,如BIO对,必须先将数据写入BIO或从BIO中检索,然后才能继续。)

您的代码实际上禁用了非阻塞I / O. 当您将0作为FIONBIO的参数值传递给ioctlsocket时,记录为:

FIONBIO

* argp参数是指向unsigned long值的指针。 如果应启用 非阻塞模式,则将* argp设置为非零值;如果应禁用非阻塞模式,则将* argp设置为零 。 [..]

https://msdn.microsoft.com/en-us/library/windows/desktop/ms738573%28v=vs.85%29.aspx