Muduo网络库源码分析(一) EventLoop事件循环(Poller和Channel)
来源:互联网 发布:linux搭建局域网 编辑:程序博客网 时间:2024/05/22 12:18
转自:http://blog.csdn.net/nk_test/article/details/51052539
(一)TCP网络编程的本质:三个半事件
1. 连接的建立,包括服务端接受(accept) 新连接和客户端成功发起(connect) 连接。TCP 连接一旦建立,客户端和服务端是平等的,可以各自收发数据。
2. 连接的断开,包括主动断开(close 或shutdown) 和被动断开(read(2) 返回0)。
3. 消息到达,文件描述符可读。这是最为重要的一个事件,对它的处理方式决定了网络编程的风格(阻塞还是非阻塞,如何处理分包,应用层的缓冲如何设计等等)。
3.5 消息发送完毕,这算半个。对于低流量的服务,可以不必关心这个事件;另外,这里“发送完毕”是指将数据写入操作系统的缓冲区,将由TCP 协议栈负责数据的发送与重传,不代表对方已经收到数据。
这其中,最主要的便是第三点: 消息到达,文件描述符可读。下面我们来仔细分析(顺便分析消息发送完毕):
(1)消息到达,文件可读:
内核接收-> 网络库可读事件触发--> 将数据从内核转至应用缓冲区(并且回调函数OnMessage根据协议判断是否是完整的数据包,如果不是立即返回)-->如果完整就取出读走、解包、处理、发送(read decode compute encode write)
(2)消息发送完毕:
应用缓冲区-->内核缓冲区(可全填)--->触发发送完成的事件,回调Onwrite。如果内核缓冲区不足以容纳数据(高流量的服务),要把数据追加到应用层发送缓冲区中内核数据发送之后,触发socket可写事件,应用层-->内核;当全发送至内核时,又会回调Onwrite(可继续写)
(二)事件循环类图
EventLoop类:
EventLoop是对Reactor模式的封装,由于Muduo的并发原型是 Multiple reactors + threadpool (one loop per thread + threadpool),所以每个线程最多只能有一个EventLoop对象。EventLoop对象构造的时候,会检查当前线程是否已经创建了其他EventLoop对象,如果已创建,终止程序(LOG_FATAL),EventLoop类的构造函数会记录本对象所属线程(threadld_),创建了EventLoop对象的线程称为IO线程,其功能是运行事件循环(EventLoop:loop),啥也不干==
下面是简化版的EventLoop(内部的Poller尚未实现,只是一个框架)
EventLoop.h
Poller类:
时序图:
Poller是个抽象类,具体可以是EPollPoller(默认) 或者PollPoller,需要去实现(唯一使用面向对象的一个类)
对于PollPoller来说,存在一个map,用来关联fd和channel的,我们可以根据fd快速找到对应的channel。一个fd对应一个struct pollfd(pollfd.fd),一个fd 对应一个channel*;这个fd 可以是socket, eventfd, timerfd, signalfd。Poller的作用是更新IO复用中的channel(IO事件),添加、删除Channel。我们看一下PollPoller的实现:
PollPoller.h
PollPoller.c
代码中的几个技巧都在注释中标出。
Channel类:
Channel是selectable IO channel,负责注册与响应IO 事件,它不拥有file descriptor。
Channel是Reactor结构中的“事件”,它自始至终都属于一个EventLoop(一个EventLoop对应多个Channel,处理多个IO),负责一个文件描述符的IO事件,它包含又文件描述符fd_,但实际上它不拥有fd_,不用负责将其关闭。在Channel类中保存这IO事件的类型以及对应的回调函数,当IO事件发生时,最终会调用到Channel类中的回调函数。Channel类一般不单独使用,它常常包含在其他类中(Acceptor、Connector、EventLoop、TimerQueue、TcpConnection)使用。Channel类有EventLoop的指针 loop_,通过这个指针可以向EventLoop中添加当前Channel事件。事件类型用events_表示,不同事件类型对应不同回调函数。
以下两个都由Channel注册:
Acceptor是被动连接的抽象--->关注监听套接字的可读事件,回调handleRead。
Connector对主动连接的抽象。
时序图:
Channel.h
Channel.c这三个类之间的关系不难理解,其实本质就是一个Poll/Epoll,只不过进行了更高的抽象后划分出来的这些类,重点理解博客开头的那张类图即可。参考:
《Muduo使用手册》
《linux多线程服务端编程》
- Muduo网络库源码分析(一) EventLoop事件循环(Poller和Channel)
- Muduo网络库源码分析(一) EventLoop事件循环(Poller和Channel)
- muduo源码分析之EventLoop、Channel、Poller的实现
- muduo网络库学习之EventLoop(一):事件循环类图简介和muduo 定时器TimeQueue
- muduo : Reactor(EventLoop Poller Channel)
- muduo网络库学习(四)事件驱动循环EventLoop
- muduo:Channel、Poller分析
- Muduo网络库源码分析(三)线程间使用eventfd通信和EventLoop::runInLoop系列函数
- Muduo网络库源码分析(三)线程间使用eventfd通信和EventLoop::runInLoop系列函数
- muduo网络库学习之EventLoop(二):进程(线程)wait/notify 和 EventLoop::runInLoop
- muduo库阅读(29)——Net部分:Reactor(EventLoop事件循环)
- muduo网络库学习(二)对套接字和监听事件的封装Channel
- muduo源码分析之事件处理器-Channel
- muduo源码分析---EventLoop类
- muduo源码分析之EventLoop
- muduo网络库学习之EventLoop(七):TcpClient、Connector
- muduo网络库学习(一)对io复用的封装Poller,面向对象与基于对象
- muduo库阅读(35)——Net部分:用于执行事件循环(EventLoop)的线程类EventLoopThread
- Windows读取文件的版本信息
- kali linux攻击机及windowsXp/Metasploit_linux靶机安装及在此基础上的蜜罐系统搭建(上)
- 学习Hadoop遇到的问题
- 在tp中实现单个用户禁止重复登录
- Beego应用开发01
- Muduo网络库源码分析(一) EventLoop事件循环(Poller和Channel)
- 2017 上半年最酷,最受欢迎的30 个 Android 库
- iOS中集成ijkplayer视频直播框架
- 用Runtime.getRuntime().exec()需要注意的地方
- uuid 生成方法
- 微服务框架选择:Spring Cloud还是Dubbo?
- 剑指offer-操作给定的二叉树,将其变换为源二叉树的镜像
- CentOS-6.5安装与配置Tomcat-7
- constexpr-not-compiling-in-vc2013