Boost Asio SSL第二次无法接收数据(第一次OK)

时间:2018-06-05 06:45:35

标签: c++ ssl boost openssl boost-asio

我正在使用Boost Asio和Boost Beast来处理简单的RESTful服务器。对于普通的HTTP和TCP套接字,它可以很好地工作。我用JMeter进行负载测试,一切正常。

我尝试添加SSL套接字。我设置了' ssl :: context'并且还称为'async_handshake()' - 与普通套接字相比,SSL的其他步骤。它仅适用于第一次。客户端可以与我(服务器)连接,我也可以通过' boost :: beast :: http :: async_read()'来接收数据。

因为这是RESTful,所以在请求之后连接将会丢失&响应。我打电话给' SSL_Socket.shutdown()'并遵循SSL_Socket.lowest_layer()。close()'关闭SSL套接字。

当下一个传入请求时,客户端能够与我(服务器)连接。我打电话给' SSL_Socket.async_handshake()'然后按照' boost :: beast :: http :: async_read()'进行操作。但这次我无法接收任何数据。但是这种联系已经成功建立。

任何人都知道我错过了什么?

非常感谢!

3 个答案:

答案 0 :(得分:0)

我设法通过切换' ssl :: stream'来解决问题。 socket to' boost :: optional'然后添加了SSL_Socket.emplace(io_context,oSSLContext)'每次关闭和关闭套接字时。

值得称赞的是{&#39; Can't implement boost::asio::ssl::stream<boost::asio::ip::tcp::socket> reconnect to server&#39;。他的声明&#34; 最纯粹的解决方案是不重用流/套接字对象&#34;石头!节省我的时间。

感谢。

答案 1 :(得分:0)

我遇到了类似的问题,第二次以后,异步接收始终失败,会话ID未初始化。

我解决了在上下文中调用SSL_CTX_set_session_id_context的问题, 在上下文选项上使用SSL_SESS_CACHE_OFF和SSL_OP_NO_TICKET设置上下文缓存模式。

这是我对别人问题的看法。

答案 2 :(得分:0)

如果要重用流实例,则需要使用openssl lib函数来操作SSL_Socket.native_handle()。 ssl关闭后,在开始新的ssl握手之前使用SSL_clear()

请仔细阅读(注意警告)link

  

SSL_clear()重置SSL对象以允许另一个连接。但是,重置操作会保留上一次会话的一些设置(其中一些设置是在上一次握手期间自动进行的)   .........

     

警告

     

SSL_clear()重置SSL对象以允许另一个连接。但是,重置操作保留了上次会话的一些设置(其中一些设置是在上一次握手期间自动进行的)。只有与共享这些设置的完全相同的对等方建立新连接才有意义,并且如果该对等方在连接之间更改其设置可能会失败。使用顺序SSL_get_session(3); SSL_new(3); SSL_set_session(3);而是使用SSL_free(3)来避免此类故障(或者如果不需要会话重用,则只需使用SSL_free(3); SSL_new(3))。

关于ssl关机问题,link解释了boost asio ssl关机如何工作。

  

在Boost.Asio中,如果发生错误或当事方已发送和接收到close_notify消息,则将shutdown()操作视为完成。

如果您查看boost.asio(1.68)源代码boost \ asio \ ssl \ detail \ impl \ engine.ipp,它将显示boost.asio如何进行ssl关闭,并且 stream_truncated是未收到来自对等端的要读取的数据或ssl关闭

int engine::do_shutdown(void*, std::size_t)
{
  int result = ::SSL_shutdown(ssl_);
  if (result == 0)
    result = ::SSL_shutdown(ssl_);
  return result; 
} 
const boost::system::error_code& engine::map_error_code(
    boost::system::error_code& ec) const
......
// If there's data yet to be read, it's an error.
if (BIO_wpending(ext_bio_))
{
    ec = boost::asio::ssl::error::stream_truncated;
    return ec;
}
......
// Otherwise, the peer should have negotiated a proper shutdown.
if ((::SSL_get_shutdown(ssl_) & SSL_RECEIVED_SHUTDOWN) == 0)
{
    ec = boost::asio::ssl::error::stream_truncated;
}
}

此外,您还可以看到boost.asio ssl关闭例程可能在第一次返回0的情况下两次调用openssl SSL_shutdown(),openssl文档允许它,但是建议如果第一次返回{{1},则调用SSL_read()进行双向关闭}返回0。

阅读link了解详情。