muduo库的事件框架

来源:互联网 发布:星际航行概论 知乎 编辑:程序博客网 时间:2024/05/22 13:09


TCP网络编程本质

TCP网络编程编程本质是处理三个半事件。

1.连接建立:服务器accept(被动)接收连接,客户端connect(主动)发起连接。

2.连接断开:主动断开(close、shutdown),被动断开(read返回0)

3.消息到达:文件描述符可读

4.消息发送完毕:这算半个事件。对于低流量的服务,可以不关心这个事件。这里的发送完毕是数据写入操作系统缓冲区,将由TCP协议栈法则数据的发送与重传,不代表对方已经接数据。高流量服务可能导致内核缓冲区满了,数据还会追加到应用层缓冲区。


事件处理框架:

来看主要的两个类图:


用connectCallback一个方法包含了连接建立和连接断开。messageCallback处理消息达到事件。writeCompleteCallback处理消息发送完毕事件。

使用举例,EchoServer:


EchoServer包含TcpServer对象,采用基于对象的编程思想。

我们编程只需要定义一个服务器类,包含TcpServer类,然后注册自己的onMessage和onConnection函数即可。


EventLoop的支持

1.muduo库遵循one loop per thread 意思是说每个线程最多有一个EventLoop对象。

2.EventLoop对象构造的时候,会检查当前线程是否已经创建了其他EventLoop对象,如果已经创建,终止程序(LOG_FATAL)。

3.EventLoop构造函数会记住本线程对象所对应的threadid_

4.能创建EventLoop对象的线程成为IO线程,其功能是运行事件循环,EventLoop::Loop

5.muduo库支持multiple reactors + thread pool,每一个reactor一个线程,也就是每个线程最多一个EventLoop对象。


事件封装大框架

我们看一下整个事件处理大框架类图:


白色部分表示对外可见,黑色对外不可见。
1.Poller是一个抽象类,有三个纯虚函数。有两个派生类,PollPoller和EPollPoller,采用不同的I/O复用机制。这是整个muduo库少有的使用面向对象思想封装,它们都是内部类,mudo库对外没有使用面向对象思想暴露接口的。EventLoop的loop()函数调用Poller的poll()函数实现的。和EventLoop是组合关系。
2.Channel是对I/O事件注册与响应的封装。它的update()函数负责注册或者更新I/O可读可写事件。handleEvent()函数负责对发生事件的处理。一个EventLoop包含多个channel,可以用来捕捉多个通道的可读可写事件。EventLoop和Channel是聚合关系。Channel实际上不拥有文件描述符,析构不会close描述符。
3.FileDesciptor是被Socket对象拥有的,并负责释放close()。
4.Channel是Acceptor和Connector的成员,组合关系,所以生命期被它们管理。Channel向Acceptor和Connector注册回调函数。可读事件发生后,handleEvent从而调用handleRead()响应。一旦可写,调用Connector中的相关函数响应。
5.Acceptor的生存期由TcpServer决定。同样Connector由TcpClient决定。
6.TcpConnection是被动连接和主动连接产生后产生的,它的生存期由连接生存期决定。





0 0