boost::asio 连接管理11 如何关闭连接
在实际产品运行中,对连接管理有了更新的认识,这里分享一下。
shared_ptr管理连接对象的生命周期
shared_ptr的引用计数器决定了连接对象的生命周期。这里我说的连接对象就是在我的前文:http://blog.csdn.net/csfreebird/article/details/8522620
中的Client对象:
- #include "core/connection.h"
- #include <vector>
- using namespace std;
- class Client: public Connection<Client> {
- public:
- Client(io_service& s);
销毁连接对象的条件
那么什么情况下shared_ptr的引用技术会变成0呢?必须满足下列所有条件:
1. 如果你不再发起任何异步读/写操作
因为每一次异步读/写操作都会将Client对象自己的this指针包装成shared_ptr,通过bind交给boost asio框架,此时框架将持有该shared_ptr,直到读/写完成,回调我们自己的函数后才会将引用计数器减1。
2. 如果没有任何其他对象或者容器持有这个shared_ptr。
实际通信程序为了实现服务器事件通知,我会将所有的Client对象的shared_ptr保存在一个容器中,比如map。然后定期的检查这些Client有没有在数据库中有事件要发布,如果有,则调用Client的方法发送数据。也会定期检查Client对象代表的连接上的心跳消息,如果心跳超时,则将share_ptr从map中移除掉,并停止任何读/写的异步操作(也就是上上面第一个条件)
只有在满足了这两个条件的情况下,shared_ptr会自动销毁Client对象,Client对象内部的成员变量socket也会被销毁。
一般情况下不需要手动关闭socket
所以,我之前用下面的函数关闭socket一般情况下是不需要的
- void CloseSocket() {
- try {
- socket.shutdown(tcp::socket::shutdown_both);
- socket.close();
- } catch (std::exception& e) {
- BOOSTER_INFO("Connection") << "thread id: " << this_thread::get_id() << e.what() << endl;
- }
- }
多线程环境下关闭连接导致crash
如果要使用CloseSocket,多线程环境下必须小心。比如我碰到过这样的情况:一个线程检查到了超时,然后调用Client::CloseSocket方法,同时另一个线程正在该Client上发起了异步的读/写操作,结果进程崩溃了。boost asio不允许这样做。
参考:http://web.archiveorange.com/archive/v/Q0J4VefPMc2v8QYvcVr3
异步读/写阻塞导致连接对象无法销毁
如果就坚持不用CloseSocket行么,我碰到另一种情况,async_write/async_read会阻塞,结果shared_ptr的引用计数不会为0,所以Client对象无法被销毁。那么怎么安全的调用CloseSocket的呢?用strand,下面是代码:
- void Client::ToClose() {
- strand_.post(bind(&Client::DoClose, shared_from_this()));
- }
- void Client::DoClose() {
- CloseSocket();
- }
其他线程就只需要调用ToClose函数即可。
由于strand_.post的桥梁作用,CloseSocket会在io_service运行的线程池中被保护。就不会出现和async_read/async_write同时被执行的情况。
在实际编程中我们可能由于很多原因要关闭连接,比如前面说的心跳超时,也有收到了不正确的数据,或者在asio传递出来的网络错误,又或者是收到了关闭进程的信号。
无论何种原因,都可以采用上面的方式进行关闭连接。所以原则只有一个,记住shared_ptr的生命周期即可。
优雅的关闭进程
如何在这种情况下优雅的退出进程是个问题,否则退出时程序会crash,留下core文件。这种情况是:
1. 线程池中运行这io_service对象,进行异步的读/写操作
2. 一个线程定期检查数据库中的事件消息,并发送给所有远程终端,同时检查每个连接的心跳超时时间。
3. 一个全局的map对象保存了所有Client的shared_ptr。
在以后的文章中会探索。
boost::asio 连接管理11 如何关闭连接的更多相关文章
- TCP系列04—连接管理—3、TCP连接的半打开和半关闭
在前面部分我们我们分别介绍了三次握手.四次挥手.同时打开和同时关闭,TCP连接还有两种场景分别是半打开(Half-Open)连接和半关闭(Half-Close)连接.TCP是一个全双工(Full-Du ...
- TCP系列03—连接管理—2、TCP连接的同时打开和同时关闭
在前面的内容中我们介绍了TCP连接管理中最常见的三次握手方式和四次挥手的方式.但是有可能A和B两端同时执行主动打开并连接对方或者同时执行主动关闭连接(尽管发生这种情况的可能性比较低低),这个时候的流程 ...
- TCP系列07—连接管理—6、TCP连接管理的状态机
经过前面对TCP连接管理的介绍,我们本小节通过TCP连接管理的状态机来总结一下看看TCP连接的状态变化 一.TCP状态机整体状态转换图(截取自第二版TCPIP详解) 二.TCP连接建立 ...
- TCP系列05—连接管理—4、TCP连接的ISN、连接建立超时及TCP的长短连接
一.TCP连接的ISN 之前我们说过初始建立TCP连接的时候的系列号(ISN)是随机选择的,那么这个系列号为什么不采用一个固定的值呢?主要有两方面的原因 防止同一个连接的不同实例(di ...
- HTTP协议建立连接、通讯与关闭连接全过程
为解决服务器TimeWait多的问题,了解了一下TCP/IP协议的连接过程.以访问一静态页面为例,从建立连接到访问拿到数据,然后关闭的整个过程.使用EtherPeek截图如下: 图首为一次交互过程 ...
- 基于java 的websocket的聊天功能,一开始初始化websocket,执行打开连接之后就直接关闭连接了。
1 错误描述: java 后台没有报错,但是就是连接不上,一连上又自动关闭. 2 错误根源: 缺少jar包. 对比了报错的tomcat 的jar包和不报错的jar包 发现是tomcat下缺少上图绿色框 ...
- 前端学HTTP之连接管理
前面的话 HTTP连接是HTTP报文传输的关键通道.要掌握HTTP就需要理解HTTP连接的来龙去脉以及如何使用这些连接 如果想查看一个网页,浏览器收到URL时,会执行下图所示的步骤.将服务器的IP地址 ...
- Mybatis 打开连接池和关闭连接池性能对比
1 创建数据库表 -- phpMyAdmin SQL Dump -- version 4.2.11 -- http://www.phpmyadmin.net -- -- Host: localhos ...
- Netty中的连接管理
连接管理是我们首先需要关注的,检测空闲连接以及超时对于及时释放资源来说是至关重要的.由于这是一项常见的任务,Netty特地为它提供了几个ChannelHandler实现. 用于空闲连接以及超时的Cha ...
随机推荐
- ORACLE uuid自己主动生成主键
-- Create table create table TECHNOLOGYCOMPANY ( ID VARCHAR2(32) default SYS_GUID() not null, FLOWID ...
- MVC 返回 view
RedirectToAction(),即直接返回相同Controller的Index方法: 这个方法还有其他重载方法,比如第二个参数是Controller名,可以指定其他Controller下的Vie ...
- iOS 如何自定义NavigationBar的高度
UINavigationBar的高度在苹果官方的SDK中是固定的44个点,但是实际项目中我们却有可能遇到这样的情况,如下图: 这样的一个UINavigationBar的高度达到了84个点,这就需要我们 ...
- Linux DM9000网卡驱动程序完全分析
Linux DM9000网卡驱动程序完全分析http://blog.csdn.net/ypoflyer/article/details/6209922
- Android:AysncTask异步加载
以下是链接: http://blog.csdn.net/abc5382334/article/details/17097633 http://keeponmoving.iteye.com/blog/1 ...
- 2014 HDU多校弟六场J题 【模拟斗地主】
这是一道5Y的题目 有坑的地方我已在代码中注释好了 QAQ Ps:模拟题还是练的太少了,速度不够快诶 //#pragma comment(linker, "/STACK:16777216&q ...
- RAR压缩解压命令
RAR压缩解压命令 这几天一直没空更新博客,现在补上: 先介绍一下rar的命令格式及相关参数含义(摘自rar): 用法: rar <命令> -<开关 1> -<开关 ...
- mongodb副本集自动切换修复节点解决方案
副本集部署 1.启动mongod 在每台运行mongod服务的机器上增加配置文件/etc/mongodb-rs.conf,内容为: [root@MongodbF-A etc]# vi /etc/mon ...
- EXT.NET高效开发(三)——使用Chrome浏览器的开发人员工具
这篇帖子老少皆宜,不分男女,不分种族,不分职业.俗话说:“磨刀不误砍柴工”.掌握一些开发工具的使用,对自己帮助是很大的(无论是用于分析问题,还是提高生产力).本篇就讲述如何利用Chrome浏览器(这里 ...
- Java--格式化输出
Java的格式化输出等同于String.Format,与C有很大的相似,比如 System.out.printf("%8.2f", x); 在printf中,可以使用多个参数,例如 ...