boost::io_service 的使用 & 如何检查网络通讯正常?心跳包机制 or Detection of Half-Open (Dropped) Connections
来源:互联网 发布:java链表的实现 编辑:程序博客网 时间:2024/05/17 02:39
see link: http://blog.stephencleary.com/2009/05/detection-of-half-open-dropped.html
- 首先明确一点,通过ping这种方式来检查wamp服务器是否连接正常存在一些缺点。ping工作在 ip 层(ICMP),能够ping通不能保证 tcp/ip以及其他依赖tcp/ip的高级协议工作正常。
- 二次连接正常也不能保证通讯正常。
下面通过boost timer写了一个最简单直接的检查网络是否连接正常的模块(远端必须周期性地触发 reset 函数,否则定时器超时,表示网络连接有问题):
class HeartBeatService { public: HeartBeatService(boost::asio::io_service* p_io_service, unsigned int interval): p_io_service_(p_io_service), interval_(interval), // second timer_(new boost::asio::deadline_timer(*p_io_service)), flag_(false) {} HeartBeatService(const HeartBeatService& other): p_io_service_(other.p_io_service_), interval_(other.interval_), timer_(new boost::asio::deadline_timer(*other.p_io_service_)), flag_(other.flag_) {} ~HeartBeatService() { delete timer_; } // Schedule the timer for the first time // The timer will fire after interval_ from io_service start run bool start() { timer_->expires_from_now(interval_); timer_->async_wait(boost::bind(&HeartBeatService::check, this, boost::asio::placeholders::error)); } // 远端调用, reset flag void reset() { flag_ = false; } bool getFlag() // For test { return flag_; } private: void check(const boost::system::error_code& e) // timer 定时检查, 并设置标志 { if( e ) { // TODO print error message return; } if(flag_) { //TODO notify the controller offline! std::cerr << "TimeOut warning! The connection is lost!" } else { timer_->expires_at(timer_->expires_at() + interval_); timer_->async_wait(boost::bind(&HeartBeatService::check, this, boost::asio::placeholders::error)); flag_ = true; } } boost::asio::io_service* p_io_service_; boost::posix_time::seconds interval_; // 超时时间 boost::asio::deadline_timer* timer_; // not copyable, so use pointer bool flag_; };
用 google test 编写单元测试,测试HeartBeatService类
#include <iostream>#include <thread>#include <future>#include <boost/asio.hpp>#include <gtest/gtest.h>TEST(MyProject, HeartBeatTest){ boost::asio::io_service io; unsigned int seconds = 3; // 设定超时时间,客户端必须在这个时间内周期性地调用 reset函数 HeartBeatServicet(&io, seconds); EXPECT_TRUE(t.start()); // 调用 io_service::run, 定时器开始计时 // 或者:auto future = std::async(std::launch::async, [&]{io.run();}); // better std::thread io_thread(boost::bind(&boost::asio::io_service::run, &io)); std::this_thread::sleep_for(std::chrono::seconds(2)); // 等待 2s EXPECT_FALSE(t.getFlag()); // default is false std::this_thread::sleep_for(std::chrono::seconds(2)); // 等待 2s EXPECT_TRUE(t.getFlag()); // 定时器设置为3 sec,现在已经超时,所以会将flag设置为 true t.reset(); // 清除 flag EXPECT_FALSE(t.getFlag()); std::this_thread::sleep_for(std::chrono::seconds(4)); // 再次等待超时 EXPECT_TRUE(t.getFlag()); // 已经超时,并且设置了标志位为true testing::internal::CaptureStderr(); // 超时了会有打印信息,捕获打印 std::this_thread::sleep_for(std::chrono::seconds(3)); // 再次等待超时,如果flag为true,并且再次等待超时则会打印信息//// std::string output1 = testing::internal::GetCapturedStdout(); // expect output std::string output = testing::internal::GetCapturedStderr(); // expect output EXPECT_FALSE(output.empty()); std::cerr << output << std::endl; io.stop(); io_thread.join();}int main (int argc, char** argv){ ::testing::InitGoogleTest(&argc, argv); return RUN_ALL_TESTS();}
io_service.run 的使用注意
如果调换上述代码的顺序:
boost::asio::io_service io; std::thread io_thread(boost::bind(&boost::asio::io_service::run, &io)); // 先运行 io_service::run unsigned int seconds = 3; // 设定超时时间,客户端必须在这个时间内周期性地调用 reset函数 HeartBeatServicet(&io, seconds); EXPECT_TRUE(t.start()); // 再开始计时
如果按照先调用 io.run()
再初始化计时器的顺序,则 io_service
会检测没有处理的消息,会马上返回。为了避免出现这种情况,可以手动加一个 boost::asio::io_service::work
以避免 io.run()
返回, see link: http://stackoverflow.com/questions/35945490/keep-io-service-alive。
析构 boost::asio::io_service::work
并调用 io.stop()
会使得 io.run()
立刻返回。
io_service
有很多非阻塞的调用方式( io.poll, io.poll_one, io.dispatch
etc.) ,但是推荐最好的处理方式还是调用 io.run()
0 0
- boost::io_service 的使用 & 如何检查网络通讯正常?心跳包机制 or Detection of Half-Open (Dropped) Connections
- Detection of Half-Open (Dropped) Connections
- Detection of Half-Open (Dropped) TCP/IP Socket Connections
- (boost::format)io_service和io_service::work的基础使用
- socket的心跳包机制
- 心跳包机制及Socket通信服务的心跳包
- 心跳包机制及Socket通信服务的心跳包
- 心跳包机制及Socket通信服务的心跳包
- 心跳包机制及Socket通信服务的心跳包
- 心跳包机制及Socket通信服务的心跳包
- 心跳包机制及Socket通信服务的心跳包
- 心跳包机制及Socket通信服务的心跳包
- Boost.asio的简单使用(timer,thread,io_service类)
- Boost.asio的简单使用(timer,thread,io_service类)
- 使用boost io_service时,需要注意的东西
- boost asio中io_service类的几种使用
- boost-io_service的工作方式
- 为什么要有心跳包的机制
- HTTP基本原理(浏览器缓存)
- Ajax学习(3)数据格式提要
- NOIP 2009 最优贸易
- 82. Remove Duplicates from Sorted List II
- uva673 Parentheses Balance
- boost::io_service 的使用 & 如何检查网络通讯正常?心跳包机制 or Detection of Half-Open (Dropped) Connections
- 回调思想和钩子函数的区别
- 计算Windows下目录大小
- 2014华为上机题C++编程
- Android-Universal-Image-Loader 属性设置
- Android 开发测试环境切换工具
- SLF4J versions 1.4.0 and later requires log4j 1.2.12 or later
- hibernate @Entity @Table 实体类中不可以随便添加与表字段不对应的get方法,如增加请加注解 @Transient
- Ddr2,ddr3,ddr4内存条的读写速率