如果 winsock2 套接字是非阻塞的,与之关联的 SSL 对象是不是也会表现出非阻塞行为?

Posted

技术标签:

【中文标题】如果 winsock2 套接字是非阻塞的,与之关联的 SSL 对象是不是也会表现出非阻塞行为?【英文标题】:If a winsock2 socket is non-blocking, would an SSL object associated with it also exhibit non-blocking behavior?如果 winsock2 套接字是非阻塞的,与之关联的 SSL 对象是否也会表现出非阻塞行为? 【发布时间】:2015-04-22 18:16:23 【问题描述】:

我问这个问题是因为我不确定 SSL 对象是否像对待 BIO 对象那样将套接字视为消息的接收器/源。我的直觉告诉我是的,但我不确定。

目标: 我正在将 SSL 身份验证集成到现有的 TCP 代码中。我不想调用传统的 send()/receive(),而是希望通过 OpenSSL 的 SSL_read()/SSL_write() 来引导消息。我的另一个要求是通信是非阻塞的,并且可以部分发送数据。

以下是我如何将 SSL 对象与套接字(服务器代码)相关联。

SSL_Init(std::wstring &peer_hostname, SOCKET sock)
        //...
        //Initialize SSL structure
                ssl = SSL_new(context);
                if (ssl == NULL)
                    mr = APPZRETURN(E_FAIL, L"%ls (%d) : SSL_new failed. Unable to create SSL structure", __FUNCTIONW__, __LINE__);
                

                //Agent uses winsock class, but OpenSSL uses unix socket. Surpressed warning added here for 4244. It works
                if (SSL_set_fd(ssl, sock) == 0)    //set file descriptor for ssl
                    //Operation failed
                    return -1;
        
        //...
        int status = SSL_accept(ssl);   
        SSL_set_mode(ssl, SSL_MODE_ACCEPT_MOVING_WRITE_BUFFER|SSL_MODE_ENABLE_PARTIAL_WRITE);
        //...
    

根据 SSL_read() [https://www.openssl.org/docs/ssl/SSL_read.html] 的文档,如果底层 BIO 是非阻塞的,则 SSL 是非阻塞的。如果我的假设是正确的,这是否意味着如果套接字是非阻塞的,那么 SSL 也是如此?

我的问题的扩展:winsock tcp socket默认是非阻塞的(假设我已经创建了一个TCP socket,但没有调用ioctlsocket并设置非阻塞模式)

感谢您抽出宝贵时间阅读本文。非常感谢。

【问题讨论】:

【参考方案1】:

如果我的假设是正确的,这是否意味着如果套接字是非阻塞的,那么 SSL 也是如此?

是的。

默认是winsock tcp socket非阻塞(假设我已经创建了一个TCP socket,但是没有调用ioctlsocket并设置非阻塞模式)

默认情况下,Unix 套接字是阻塞的。没用过Winsock。但我确信 Winsock 默认应该是阻塞的。

【讨论】:

谢谢。 winsock 是相当于 Unix 套接字库的 Windows 库。 Winsock 套接字在默认情况下确实是阻塞【参考方案2】:

试试下面的代码:

   SSL_set_fd(ss, sock);
retry:
   int ret = SSL_accept(ssl);
   if (ret != 1) 
      int err = SSL_get_error(ssl, ret);
      if (err == SSL_ERROR_WANT_READ || SSL_ERROR_WANT_WRITE) 
         // maybe need some sleep or select
         goto retry;
      
   

【讨论】:

以上是关于如果 winsock2 套接字是非阻塞的,与之关联的 SSL 对象是不是也会表现出非阻塞行为?的主要内容,如果未能解决你的问题,请参考以下文章

在winsock2中使用选择

如何中止winsock阻塞调用?

如何将 TCP 套接字更改为非阻塞?

Winsock2 tcp/ip - 一些数据包被忽略可能是由于前一个数据包的空终止符

Winsock2 select():同一个套接字上的多个事件是可能的?

Winsock2 - 如何使用 MSG_WAITALL 打开允许 ​​recv() 的 TCP 套接字?