c++ - 断开连接后重新连接 boost beast (asio) websocket 和 http 连接时出错

标签 c++ boost tcp boost-asio boost-beast

我正在创建一个使用 ssl Websocket 连接和 ssl Http(保持事件)连接连接到服务器的客户端应用程序,我正在使用 boost::beast 包来执行相同的操作.为了检测死连接,我实现了一个简单的乒乓机制。这些都很好,但是在处理 ping-pong 故障时出现了问题。问题如下:

为了测试我的代码,我连接到远程服务器,发送了一些消息,然后关闭了我的 wifi。正如预期的那样,在一段时间后它检测到它没有收到来自服务器的任何消息,它尝试为 http 连接执行 async_shutdown 并为 websocket 连接执行 async_close .我注意到的第一件事是,在 wifi 恢复之前,这两个调用都会阻塞它们各自的链。

并且在 wifi 启动后,应用程序会尝试在重新连接之前重置流:

void HttpKeepAliveConnection::recreateSocket()
{
    _receivedPongForLastPing = true;
    _sslContext.reset(new boost::asio::ssl::context({boost::asio::ssl::context::sslv23_client}));
    _stream.reset(new HttpStream(_ioContext, *_sslContext));
}

并为 websocket 重置 ws 变量:

void WebsocketConnection::recreateSocket()
{
    _receivedPongForLastPing = true;
    _sslContext.reset(new boost::asio::ssl::context({boost::asio::ssl::context::sslv23_client}));
    _ws.reset(new WebSocket(_ioContext, *_sslContext));
}

不幸的是,它在 on_connect 或 on_ssl_handshake 失败。以下是我的日志:

156 AsioConnectionBase.cpp:53 (2018-08-06 15:34:38.458536) [0x00007ffff601e700] : Started connect sequence. Connection Name: HttpKeepAliveConn

157 AsioConnectionBase.cpp:122 (2018-08-06 15:34:38.459802) [0x00007ffff481b700] : Failed establishing connection to destination. Connection failed. Connection Name: HttpKeepAliveConn. Host: xxxxxxxxx. Port: 443. Error: Operation canceled

158 APIManager.cpp:175 (2018-08-06 15:34:38.459886) [0x00007ffff481b700] : Received error callback from connection. Restarting connection in a sec. Connection Name: HttpKeepAliveConn

159 AsioConnectionBase.cpp:53 (2018-08-06 15:34:39.460009) [0x00007ffff481b700] : Started connect sequence. Connection Name: HttpKeepAliveConn

160 HttpKeepAliveConnection.cpp:32 (2018-08-06 15:34:39.460515) [0x00007ffff481b700] : Failed ssl handshake. Connection failed.Connection Name: HttpKeepAliveConn. Host: xxxxxxxxx. Port: 443. Error: Bad file descriptor

161 APIManager.cpp:175 (2018-08-06 15:34:39.460674) [0x00007ffff481b700] : Received error callback from connection. Restarting connection in a sec. Connection Name: HttpKeepAliveConn

所以我有两个问题:

  1. 如果互联网中断并且无法正确关闭 tcp,我们如何关闭连接。
  2. 在重新连接之前 boost::beast 中的变量是什么(或者就此而言 boost::asio 因为 boost::beast 是建立在 asio 之上)需要重置

几个小时以来一直在尝试调试它。感谢任何帮助

编辑

所以我想出了我错在哪里。 Alan Birtles 和 Vinnie Falco 都是对的。在您的 ping 计时器过期(并且还没有处理程序返回)之后关闭死 ssl 连接的方法是

  1. 在你的计时器处理程序中
_stream->lowest_layer().close();

对于网络套接字

_ws->lowest_layer().close();
  1. 等待您的一个处理程序(通常是读取处理程序)返回错误(通常是 boost::asio::error::operation_aborted 错误)。从那里,排队开始下一次重新连接。 (不要在第 1 步后立即排队重新连接,这会导致我遇到的内存问题。我知道这是 asio 101,但很容易忘记)

  2. 要重置套接字,只需重置流即可

_stream.reset(new HttpStream(_ioContext, _sslContext));

对于网络套接字

_ws.reset(new WebSocket(_ioContext, _sslContext));

最佳答案

我不认为asio::ssl::stream关闭后可以再次使用。

How do we close a connection if internet is down and a proper tcp close is not possible.

简单地允许销毁套接字或流对象。

关于c++ - 断开连接后重新连接 boost beast (asio) websocket 和 http 连接时出错,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/51705787/

相关文章:

c++ - 作为 winAPI 回调的类方法

c++ - 洗牌字符串

c++ - 用于存储多种类型值的 STL 容器?

c++ - 断言是否允许模板参数

linux - rsyslog x509/certvalid需要允许的同级

testing - 我需要在客户端和服务器中使用相同版本的 iperf3 吗?

node.js - 使用 express 在 nodejs 中延迟 ack

c++使用结构指针的段错误

c++ - 使用协程隐藏阻塞操作

c++ - 你可以使用不同大小的 boost::multi_arrays 调用一个函数吗?