博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
(P34)muduo_base库源码分析:TcpConnection生存期管理
阅读量:4298 次
发布时间:2019-05-27

本文共 2317 字,大约阅读时间需要 7 分钟。

文章目录

1.TcpConnection生存期管理

  • 连接关闭时序图

    (1)一个TcpServer维护了一个已连接列表,当一个连接关闭的时候,TcpConnection的通道处于活跃状态,EventLoop的事件循环返回这个通道,并且调用handleEvent来处理;
    连接关闭属于可读事件,这里回调了TcpConnection的handleRead(),handleRead()调用read()返回为0,判断返回为0,则又调用了handleClose(),handleClose()中又回调了TcpServer中的removeConnection(),erase将连接对象从已连接列表中移除。
    (2)这里不要立即销毁连接对象TcpConnection,若销毁了TcpConnection对象,则TcpConnection对象所包含的Channel对象也会跟着销毁,而我们当前正在调用Channel对象的handleEvent(),而这个Channel对象销毁了,就会出现core dump。也即是说,TcpConnection对象的生存期要长于handleEvent()。
    (3)可以使用shared_ptr来管理TcpConnection对象。
    (i)当连接到来,创建一个TcpConnection对象,立即用shared_ptr来管理,引用计数为1,
    当Channel中维护一个weak_ptr(tie_),弱指针,将这个shared_ptr对象赋值给tie_,引用计数仍为1(由于weak_ptr是弱引用,其引用计数不会+1);
    (ii)当连接关闭,在handleEvent,将tie_提升,得到一个shared_ptr对象,引用计数就变成了2,此时erase从列表中移除,引用计数2->1,此时TcpConnection对象不会销毁。
    此外muduo的做法是:调用queueInLoop()将connectDestroyed()放到EventLoop的functors中(利用boost::bind得到一个boost::function放到functors列表中)。接着又将TcpConnection对象的引用计数+1,此时=2,handleEvent()返回后,所提升的shared_ptr局部对象销毁了,引用计数又-1,此时=1,接着boost::function又调用了用户的回调函数connCb(),调用完毕后,引用计数1->0,此时TcpConnection对象才销毁了。
    (iii)连接断开和连接建立都是调用的connCb(),removeConnection()连接断开回调函数是内部的
    在这里插入图片描述

  • eg:34\jmuduo\muduo\net\TcpConnection.h

    34\jmuduo\muduo\net\TcpConnection.cc
    34\jmuduo\muduo\net\Channel.h
    34\jmuduo\muduo\net\Channel.cc
    34\jmuduo\muduo\net\TcpServer.h
    34\jmuduo\muduo\net\TcpServer.cc

  • eg测试:34\jmuduo\tests\Reactor_test09.cc

    34\jmuduo\tests\CMakeLists.txt

  • 测试:仅看看引用计数的情况

    客户端使用telnet模拟连接建立于断开
    在这里插入图片描述
    这里处理了连接断开事件,服务端是不会出现busy-loop的
    在这里插入图片描述

  • 继承public boost::enable_shared_from_this的原因

    eg:34\esft.cpp

#include 
#include
#include
class Y: public boost::enable_shared_from_this
{
public: boost::shared_ptr
f() {
return shared_from_this(); } Y* f2() {
return this; }};int main(){
boost::shared_ptr
p(new Y);//此时p的引用计数=1 boost::shared_ptr
q = p->f();//p->f()表示当前对象转换称为shared_ptr,此时引用计数=2 Y* r = p->f2(); assert(p == q);//断言其内部的引用计数是否相等 assert(p.get() == r);//p.get()表示p里面的指针,其实就是new Y这个指针 std::cout<
<
s(r);//这里的r就是new Y这个指针,虽然2个指针的值是一样的,但是不代表shared_ptr引用计数+1,因为这里是构造了一个新的shared_ptr对象 //这里的r是裸指针,构造了一个新的shared_ptr对象 //这里若想要引用计数值+1,必须是p对象拷贝构造s,或者将对象p赋值给s std::cout<
<

测试:

在这里插入图片描述

  • eg测试:34\jmuduo\tests\Reactor_test09.cc

    34\jmuduo\tests\CMakeLists.txt

  • 测试:客户端发送aaaa6个字节(telnet尾巴还有\r\n),接着关闭客户端

    在这里插入图片描述
    客户端接收了6个字节,且回调了用户的onConnection()函数
    在这里插入图片描述

转载地址:http://emiws.baihongyu.com/

你可能感兴趣的文章
Linux(SUSE 12)安装jboss4并实现远程访问
查看>>
Neutron在给虚拟机分配网络时,底层是如何实现的?
查看>>
netfilter/iptables全攻略
查看>>
Overlay之VXLAN架构
查看>>
Eclipse : An error occurred while filtering resources(Maven错误提示)
查看>>
在eclipse上用tomcat部署项目404解决方案
查看>>
web.xml 配置中classpath: 与classpath*:的区别
查看>>
suse如何修改ssh端口为2222?
查看>>
详细理解“>/dev/null 2>&1”
查看>>
suse如何创建定时任务?
查看>>
suse搭建ftp服务器方法
查看>>
centos虚拟机设置共享文件夹并通过我的电脑访问[增加smbd端口修改]
查看>>
文件拷贝(IFileOperation::CopyItem)
查看>>
springboot(三) 用druid连接mybatis
查看>>
springboot(四) 用mybatis-generator自动生成bean和dao
查看>>
springboot(五)读写分离,多个读库,Druid监控
查看>>
springboot(六)配置swagger2
查看>>
springboot(七)redis 实现session共享
查看>>
springboot(八)拦截器之验证登录
查看>>
springboot(九)添加jsp支持
查看>>