在我的c++应用程序中,我使用OpenSSL使用非阻塞BIO连接到服务器。我正在为mac OS X和iOS开发。
第一次调用SSL_shutdown()
返回0。这意味着我必须再次调用SSL_shutdown()
:
https://www.openssl.org/docs/ssl/SSL_shutdown.html可以出现以下返回值:
0关机尚未完成。如果要执行双向关闭,则第二次调用SSL_shutdown()。SSL_get_error的输出可能具有误导性,因为即使没有发生错误,也可能标记出错误的SSL_ERROR_SYSCALL。
& lt; 0关闭失败,因为在协议级别发生了致命错误或发生了连接失败。如果需要继续非阻塞BIOs的操作,也可能发生这种情况。使用返回值ret调用SSL_get_error查找原因
到目前为止还不错。第二次呼叫SSL_shutdown()
时出现问题。这将返回-1,表示发生了错误(见上文)。现在,如果我检查SSL_get_error()
,我得到错误SSL_ERROR_SYSCALL
,这反过来意味着系统错误已经发生。但现在问题来了。如果我检查errno
,它返回0 ->未知错误。到目前为止,我所读到的问题是,这可能意味着服务器只是"挂断",但说实话,这并不能让我满意。
这是我的关机实现:
int result = 0;
int shutdownResult;
while ((shutdownResult = SSL_shutdown(sslHandle)) != 1) { //close connection 1 means everything is shut down ok
if (shutdownResult == 0) { //we are supposed to call shutdown again
continue;
} else if (SSL_get_error(sslHandle, shutdownResult) == SSL_ERROR_WANT_READ) {
[...] //omitted want read code, in this case the application never reaches this point
} else if (SSL_get_error(sslHandle, shutdownResult) == SSL_ERROR_WANT_WRITE) {
[...] //omitted want write code, in this case the application never reaches this point
} else {
logError("Error in ssl shutdown, ssl error: " + std::to_string(SSL_get_error(sslHandle, shutdownResult)) + ", system error: " + std::string(strerror(errno))); //something went wrong
break;
}
}
运行应用程序日志时:
ERROR:: ERROR in ssl shutdown, ssl ERROR: 5, system ERROR: Undefined ERROR: 0
那么这里只是服务器关闭连接还是有更严重的问题?我是不是错过了什么很明显的东西?
SSL完全关闭由两部分组成:
- 向对等端发送'close notify'警报
- 从对端接收'close notify'警报
第一个SSL_shutdown返回0,这意味着它确实向对等端发送了"关闭通知",但尚未收到任何返回。第二次调用SSL_shutdown失败,因为对等端没有执行正确的SSL关闭并返回"关闭通知",而是关闭了底层TCP连接。
这个行为实际上很常见,你通常可以忽略这个错误。无论如何,底层TCP连接是否应该关闭都无关紧要。但是,当您希望在同一TCP连接上以纯文本形式继续时,通常需要适当的SSL关闭,就像FTPS连接中的CCC命令一样(但即使有各种实现也无法正确处理这种情况)。