非阻塞套接字的 SSL_connect

5

我使用了非阻塞套接字。对于普通的TCP连接,我按照这里的方式进行操作:Non blocking socket - how to check if a connection was successful?

但是对于SSL_connect调用,我无法使其工作。

我理解应该: 1. 反复调用SSL_connect。 2. 检查SSL_get_error是否为SSL_ERROR_WANT_READ或SSL_ERROR_WANT_WRITE。 3. 如果是这样,那么我不确定该做什么。我应该继续调用SSL_connect直到我不再得到它吗?还是应该像普通套接字一样,使用read_fds或write_fds检查套接字,并使用FD_ISSET检查,如果是,则使用SO_ERROR检查getsockopt?

基本上,对于非阻塞套接字和SSL_connect,什么会告诉我连接已成功? 我已经查看了其他示例,但没有一个清晰明了。


你的猜测是正确的:根据操作结果,你应该使用 pollselect API 等待适当的套接字事件,并重复操作。 - Valeri Atamaniouk
但是我只需要调用一次SSL_connect吗?使用select时我在等待什么?如果我的套接字设置为读或写,这意味着什么?我该怎么办?我是否应该调用getsockopt? - Soft Ware
通常您将连接的套接字传递给 SSL_connect 函数。此函数不是用于低级连接操作,而是用于安全协议的设置。 - Valeri Atamaniouk
是的,我知道。我可以使用阻塞套接字进行SSL_connect。但是我对非阻塞套接字不确定。我需要整个过程的一些伪代码。 - Soft Ware
2个回答

6

这里有一个算法:

int s = socket(...);
fcntl(s, ...); // make it non-blocking
while (-1 == connect(s,...))
{
   fd_set fds;
   FD_ZERO(&fds);
   FD_SET(s, &fds);
   select(s + 1, NULL, &fds, NULL, NULL);
}

... // initialize all SSL stuff
SSL_set_fd(ctx, s);
while (-1 == SSL_connect(ssl))
{
   fd_set fds;
   FD_ZERO(&fds);
   FD_SET(s, &fds);

   switch (SSL_get_error())
   {
   case SSL_ERROR_WANT_READ:
       select(s + 1, &fds, NULL, NULL, NULL);
       break;
   case SSL_ERROR_WANT_WRITE:
       select(s + 1, NULL, &fds, NULL, NULL);
       break;
   default: abort();
   }
}
// done...

谢谢,但我不明白 select 调用的意义。它能实现什么?如果 SSL_connect != -1 或出现错误,我会停止执行。那么 select 调用能带来什么好处呢? - Soft Ware
select 阻塞执行,直到套接字变得可读或可写。即,要么网络缓冲区中有数据可以从远程对等方读取,要么输出缓冲区中有可用空间可以发送。 - Valeri Atamaniouk
我无法阻塞,所以我使用非阻塞套接字。我能做的是反复调用SSL_connect并在其间执行其他操作,是否可能只调用SSL_connect直到连接成功或出现错误?除了等待之外,select调用没有任何意义吗? - Soft Ware
当事件循环为空时,您应该进行阻塞。也就是说,当它没有其他事情要做时。如果您只是重复调用函数,那么会过度使用CPU资源。或者,如果您可以不时地调用它,它也可以以某种方式工作,但会产生额外的内核调用。 - Valeri Atamaniouk
1
好的,但是为了明确起见,只需要对 SSL_connect 进行轮询,直到它成功或失败,并出现除 WANT_READ 或 WRITE 之外的其他错误? - Soft Ware
1
SSL_connect() 仅在后台逐步处理连接工作流程。它读取或写入当前可用的数据,告诉您是否需要写入更多或读取更多,并延迟到您将套接字置于该状态,然后期望您再次调用它以便下一步继续前进。 - Dustin Oprea

0

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接