我有一个boost::beast
的SSL流数据成员:
class HttpsClient
{
...
asio::ssl::context _ssl_ctx;
beast::ssl_stream<beast::tcp_stream> _stream;
};
在构建时,我使用以下方式使用asio::io_context
和ssl上下文初始化流:
namespace ssl = boost::asio::ssl;
ssl::context sslContext()
{
ssl::context ssl_ctx {ssl::context::tlsv12_client};
ssl_ctx.set_verify_mode(ssl::context::verify_peer | ssl::context::verify_fail_if_no_peer_cert);
ssl_ctx.set_default_verify_paths();
boost::certify::enable_native_https_server_verification(ssl_ctx);
return ssl_ctx;
}
HttpsClient::HttpsClient(asio::io_context& ctx)
: _ssl_ctx(sslContext())
, _stream(ctx, _ssl_ctx)
{}
我的connect函数会同步解析端点,连接到它,并执行SSL握手。
void HttpsClient::connect(const std::string& host, std::uint16_t port, const std::string& path)
{
tcp::resolver resolver {_stream.get_executor()};
tcp::resolver::results_type end_point = resolver.resolve(host, std::to_string(port));
beast::get_lowest_layer(_stream).connect(end_point);
beast::get_lowest_layer(_stream).socket().set_option(tcp::no_delay {true});
SSL_set_tlsext_host_name(_stream.native_handle(), host.c_str());
_stream.handshake(ssl::stream_base::client);
}
连接成功后,我会开始进行async_read
操作,而当我想要发送请求时,则使用同步版本:
void HttpsClient::write(beast::http::request<beast::http::string_body>& request)
{
request.prepare_payload();
http::write(_stream, request);
}
这一切都按预期工作。
我遇到的问题是,我想断开然后重新连接流。
我尝试了几种不同的方法来关闭连接:
取消未完成的异步读取并关闭流:
_stream.next_layer().cancel();
_stream.shutdown();
一旦 shutdown
完成,我似乎能够重新连接,但尝试写入流会失败,并显示 "protocol is shutdown"
。
在收到 "protocol is shutdown"
后,任何重新连接的尝试都会受到 "Operation canceled"
的影响。
取消未完成的 async_read 并关闭底层 TCP 流:
_stream.next_layer().cancel();
_stream.next_layer().close();
一旦
close
完成,似乎仍然可以重新连接,但现在尝试写入流会失败并显示"wrong version number"
。收到
"wrong version number"
后,任何重新连接的尝试都会收到"unspecified system error"
。问题:
- 是否可以断开流,然后重新连接和重用它? - 如果可以,我需要执行哪些程序来允许此操作?