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 ...
随机推荐
- 同时支持多家云平台的管理工具HybridFox
偶然间发现了这个firefox上的开元插件 号称支持AWS,Eucalyptus,OpenStack,OpenNebula 目的是通过一个入口实现异种云平台的管理 主要功能包括: Manage Ima ...
- OpenStack里对VPN的支持
今天翻自己的笔记找到了点去年研究Cloudpipe的东西: 对于用VLAN隔开的项目内主机的访问,可以使用CloudPipe来进行VPN访问 其实就是把OpenStack和OpenVPN集成了一下,给 ...
- Linux下which、whereis、locate、find 区别
我们经常在linux要查找某个文件或命令,但不知道放在哪里了,可以使用下面的一些命令来搜索.which 查看可执行文件的位置 whereis 查看文件的位置 locate 配合 ...
- python文件I/O
file = open(filename,mode) ,python使用open或者file:打开文件,打开文件有几种模式,譬如酱紫: test = open(“txt.txt”,”w”),更多的参数 ...
- php5.3升级到5.5
在网站中发布中: / 开启调试模式 建议开发阶段开启 部署阶段注释或者设为falsedefine('APP_DEBUG',true); true没问题,改为:false就报错 报错如下: PHP Fa ...
- ELK 之二:ElasticSearch 和Logstash高级使用
一:文档 官方文档地址:1.x版本和2.x版本 https://www.elastic.co/guide/en/elasticsearch/guide/index.html 硬件要求: 1.内存,官方 ...
- Rsync、Unison及DRBD的比较
一.Rsync Rsync(remote synchronize),顾名思义,可以知道这是一个远程数据同步工具,可通过LAN/WAN快速同步多台主机间的文件.Rsync使用所谓的 “Rsync算法”来 ...
- java高级project师须要掌握的技术
1.你须要精通面向对象分析与设计(OOA/OOD).涉及模式(GOF,J2EEDP)以及综合模式.你应该十分了解UML,尤其是class,object,interaction以及statediagra ...
- ioc构架demo
1.视图 <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" xmlns:too ...
- 在android解析json
1.采用一般方式解释json为对象 package com.heimazyh.testjson; import org.json.JSONException; import org.json.JSON ...