【发布时间】:2015-11-27 18:12:34
【问题描述】:
我的应用程序的整个逻辑都使用非阻塞套接字,但在连接阶段,我发现在与SSL_connect() 执行 SSL 握手之前,最好使套接字阻塞。这是因为否则它会在握手成功完成之前创建一个繁忙的循环,并且在此之前实际上阻塞套接字应该更有效。
这是我的连接逻辑的伪代码:
bool connect(host)
{
int socket;
init_socket(socket);
set (socket, NONBLOCKING);
connect_with_timeout(socket, host, 2s);
if (timeout_failed || connect_errors) return false;
set (socket, BLOCKING);
SSL_connect (socket);
if (ssl_connect_errors) return false;
set (socket, NONBLOCKING);
return true;
}
非阻塞套接字上的 SSL 握手如下所示:
do
{
SSL_connect(socket);
}
while (!SSL_connection_errors);
像这样更改套接字类型是否被认为是一种不好的做法?当你这样做时,在低层次上真正发生了什么?
我知道这似乎是对性能的微小改进,但我想把它做好,因为我的应用程序可能会尝试每 30 秒重新连接一次,并且用户偶尔会遇到不到 1 秒的 CPU 峰值。
编辑:我在这个问题上得到的答案让我明白了如何尝试在非阻塞套接字上读取然后休眠并不是一个好主意。但是,我确实需要一个独立于平台的解决方案来解决poll,所以我已经继续添加了一个select,读取操作的超时时间为 1 秒,针对 Windows 和 Linux 进行了测试,现在 CPU 使用率较低。谢谢。
【问题讨论】:
-
改变socket的状态没有错。但是为什么不正确地握手而不阻塞呢?如果
SSL_connect会阻塞,请调用SSL_get_error并正确处理SSL_ERROR_WANT_READ和SSL_ERROR_WANT_WRITE。 -
这样做会导致我试图避免的繁忙循环。
-
不,它不会,出于同样的原因,您的读写不会导致繁忙的循环。
SSL_connect与SSL_read一样工作。 See here. -
读取确实会导致繁忙的循环,因此每次收到 EWOULDBLOCK 或 SSL_WANT_READ / WRITE 时,我都必须让线程休眠几微秒。
-
哦,那你问错问题了。你根本不明白如何进行非阻塞套接字操作。