我的情况有所不同。我使用boost::asio::ssl
编写了一个SSL客户端,但目前没有服务器可以测试,因为它是由其他组开发的。因此,本服务器只接受普通的TCP(不安全)连接。当我在服务器上使用我的ssl客户端时,阻塞handshake()
挂起/永不返回。我在网上搜索并得知Mozilla也有类似的问题 - 它在启动SSL连接到非ssl支持服务器时挂起,但他们的bug已经修复了。我只是对我的部分代码进行解释,以确保没有编码错误:
ctor
中的:
SecuredConnectionPolicy<ThreadPolicy>::SecuredConnectionPolicy() :
m_sslContext(boost::asio::ssl::context::sslv23),
m_socket(m_ioService, m_sslContext) //ssl::stream<tcp::socket>
{
}
然后当我调用“connect
(...)”时:
m_sslContext.set_options(boost::asio::ssl::context::default_workarounds);
m_sslContext.set_verify_mode(
boost::asio::ssl::context::verify_none,
errorCode
);
if(!errorCode)
{
/*m_sslContext.set_verify_callback(
[this](bool bIsPreverificationSuccessful, boost::asio::ssl::verify_context &context){return this->verificationHandler(bIsPreverificationSuccessful, context);},
errorCode
);*/
if(!errorCode)
{
m_sslContext.load_verify_file("newcert.pem", errorCode);
if(!errorCode)
{
m_socket.lowest_layer().connect(remoteEndpoint, errorCode);
if(!errorCode)
{ // ########### Following NEVER RETURNS #############
m_socket.handshake(boost::asio::ssl::stream_base::client, errorCode);
if(errorCode)
{
std::cerr << "Secured Connection Handshake Failed! " << errorCode.message() << std::endl;
}
}
else
{
std::cerr << "Secured Connection Failed! " << errorCode.message() << std::endl;
}
}
else
{
std::cerr << "Secured Connection loading certificate files from default paths Failed! " << errorCode.message() << std::endl;
}
}
else
{
std::cerr << "Registering Verification callback failed! " << errorCode.message() << std::endl;
}
}
else
{
std::cerr << "Secured Connection verify mode Failed! " << errorCode.message() << std::endl;
}
可能是什么原因?我做错了吗?
我没有提供任何verify_callback处理程序,因为我假设OpenSSL完成了预验证(因为在boost中它说它调用的是OpenSSL等效函数)应该足够了。它是否有任何缺点,或者这会影响&lt; 1&gt;?
这是一个微不足道的,但只是为了确保它不会导致问题:通常,boost中的示例显示ssl上下文对象在ssl::stream<tcp::socket>
的ctor中给出之前已设置。然而,我之前(在上面的ctor中)和之后更改了connect()
中的属性。这些是否会反映在构造的ssl :: stream的行为中(因为它需要引用,我希望它不会制作任何副本)?
在旁注(如果它有用)上,我创建了一个CA rootKey,CA自签名PEM证书,由CA证书签名的服务器证书。 CA证书就是我给load_verify_file(...)
。
答案 0 :(得分:1)
您选择调用阻塞直到完成或失败的操作,它既不会阻止,也会永久阻止。如果您不希望阻止操作明确成功或失败,请不要调用具体记录的操作来执行此操作。
如果你对另一端从未写过的连接进行了阻塞读取,你会发生什么?它会永远阻止。在这里,您已经在连接上完成了阻塞握手,而另一端永远不会与您握手。正如你所要求的那样,你的代码会一直等到它。