如何使用boost::asio从网络中断中恢复
How to recover from network interruption using boost::asio
我正在编写一个接受来自设备的数据并处理它的服务器。除非网络中断(即,如果我拔下以太网电缆,然后重新连接(,否则一切正常。我正在使用 read_until((,因为设备使用的协议以特定的字节序列终止数据包。当数据流中断时,read_until(( 会按预期进行阻塞。但是,当流再次启动时,它仍然处于阻塞状态。如果我查看Wireshark的数据流,设备继续传输,每个数据包都被网络堆栈确认。但如果我看bytes_readable它总是 0。如何检测中断以及如何重新建立与数据流的连接?下面是一个代码片段,提前感谢您提供的任何帮助。[放轻松,这是我的第一个堆栈溢出问题......是的,我确实试图寻找答案。
using boost::asio::ip::tcp;
boost::asio::io_service IOservice;
tcp::acceptor acceptor(IOservice, tcp::endpoint(tcp::v4(), listenPort));
tcp::socket socket(IOservice);
acceptor.accept(socket);
for (;;)
{
len = boost::asio::read_until(socket, sbuf, end);
// Process sbuf
// etc.
}
请记住,客户端会启动连接,因此您唯一需要做的就是重新创建套接字并重新开始接受。我将保留您的代码片段的格式,但我希望您的真实代码已正确封装。
using SocketType = boost::asio::ip::tcp::socket;
std::unique_ptr<SocketType> CreateSocketAndAccept(
boost::asio::io_service& io_service,
boost::asio::ip::tcp::acceptor& acceptor) {
auto socket = std::make_unique<boost::asio::ip::tcp::socket>(io_service);
boost::system::error_code ec;
acceptor.accept(*socket.get(), ec);
if (ec) {
//TODO: Add handler.
}
return socket;
}
...
auto socket = CreateSocketAndAccept(IOservice, acceptor);
for (;;) {
boost::system::error_code ec;
auto len = boost::asio::read_until(*socket.get(), sbuf, end, ec);
if (ec) // you could be more picky here of course,
// e.g. check against connection_reset, connection_aborted
socket = CreateSocketAndAccept(IOservice, acceptor);
...
}
脚注:不言而喻,socket
需要保持在范围内。
编辑:基于下面的评论。
侦听套接字本身不知道客户端是静音还是被切断。所有操作,尤其是同步操作,都应对完成施加时间限制。考虑设置SO_RCVTIMEO
或SO_KEEPALIVE
(每个套接字或系统范围,有关详细信息 如何正确使用SO_KEEPALIVE选项来检测另一端的客户端是否关闭?
另一种选择是异步并实现一个成熟的"共享"套接字服务器(BOOST 示例页面是一个很好的开始(。
无论哪种方式,您都可能遇到数据一致性问题并被迫处理它,例如,当客户端检测到连接中断时,它会重新发送数据。(或使用更高级别协议更复杂的协议(
如果你想保持同步,我看到的处理方式是在检测到中断时销毁套接字。阻止调用应引发可以捕获的异常,然后再次开始接受连接。
for (;;)
{
try {
len = boost::asio::read_until(socket, sbuf, end);
// Process sbuf
// etc.
}
catch (const boost::system::system_error& e) {
// clean up. Start accepting new connections.
}
}
正如 Tom 在他的回答中提到的,不活动和不优雅的断开连接之间没有区别,因此您需要一个外部机制来检测这一点。
如果您期望连续数据传输,也许服务器端的每个连接超时就足够了。一个简单的ping也可以工作。接受连接后,每 X 秒 ping 一次客户端,如果他不回答,则宣布连接失效。
- 用C++将哈希表写入文件并从文件中恢复
- 类成员和中断
- 捕获标准输出以压缩并使用 CTRL-C 中断会给出损坏的 zip 文件
- Opencv 恢复到比我设置的更高的分辨率
- 变量在使用赋值语句赋值后恢复为以前的值
- 在信号处理程序中捕获C++未处理的异常并恢复应用程序
- 我的代码运行良好,但在游戏循环中中断
- 使用带有MCP23017的 pigpio 进行中断读取
- 为什么我在 AVR 中的中断无法正常工作?
- 删除所有字符串后如何恢复 QStringList?
- 使用 UDP 中断 while()-循环
- C++:在不中断共享的情况下通过引用传递共享 PTR?
- 当对套接字 send() 的同步调用由于连接另一端丢失而被阻止时,如何恢复?
- 如何在 CompleteAsyncIO 中访问 IOMemoryBufferDescriptor,该描述符通过中断 EP
- 如何为伺服电机创建中断或返回值?
- 开关:无外壳中断
- 如何使用中断停止循环?
- 如何仅使用一次固定<<设置精度(2)?或者至少恢复到默认行为?
- 如何使用boost::asio从网络中断中恢复
- Arduino:中断昂贵的功能并恢复另一个