muduo整体介绍及Echo服务器流程分析
来源:互联网 发布:手机文件编辑软件 编辑:程序博客网 时间:2024/05/16 06:41
muduo是Ractor模式,整个核心是Reactor;EventLoop就充当了Reactor。下面就是muduo的简化类图结构:
EventLoop是one thread per loop中的loop,每个线程只能有一个EventLoop的实体,它来负责IO和定时器事件的分派。它用eventfd来异步唤醒,不同与传统的用一对pipe。它用TimerQueue作为计时管理,Poller实现IO multiplexing。
Poller是个抽象基类,它实现了pool/epoll的封装。派生类PollPoller实现了poll的封装;派生类EPollPoller实现了epoll的封装。
Channel是selectable IO channel,负责注册与响应IO事件。但是它没有file descriptor,它是TcpConnection、Acceptor、TcpConnection、TimeQueue的成员,其生命周期由后者控制。
Socket是一个RAII handle,封装了一个file descriptor,且在析构时关闭fd。它是Acceptor、TcpConnection的成员,生命周期由后者控制。EventLoop、TimeQueue中拥有fd,但是没有封装为Scokets class。
Connector用来发起TCP连接,它是TcpClient的成员,生命周期由后者控制。
Acceptor用来接收TCP连接,它是TcpServer的成员,生命周期由后者控制。
muduo网络库头文件关系如下:
其中白底为用户可见,灰底为用户不可见。
Edian.h封装了计算机字节顺序/网络字节顺序之间的转换函数,放在命名空间sockets。
SocketsOps.{h, cc}封装了了套接字fd的创建、连接、绑定、监听、关闭函数;还封装了网络地址间的转换,例如“1.2.3.4”/sockaddr_in.sin_addr.s_addr,scokaddr/sockaddr_in等之间的转换。
InetAddress.{h, cc}封装了InetAddress class,类中只有一个私有变量struct sockaddr_in addr_,封装了网络地址的一些操作。resolve实现了域名/主机名解析IP。
Socket.{h, cc}封装了fd,实现了fd常见的一些操作。它使用RAII手法,在析构时close(fd)。
下面以一个Echo服务器为例,讲解一下muduo实现Reactor的大概流程:
Echo源码为muduo自带的,为了便于理解,把封装的EchoServer拆开了。
#include <muduo/base/Logging.h>#include <muduo/net/TcpServer.h>#include <muduo/net/EventLoop.h>#include <boost/bind.hpp>//define callback functionvoid onConnection(const muduo::net::TcpConnectionPtr& conn){ LOG_INFO << "EchoServer - " << conn->peerAddress().toIpPort() << " -> " << conn->localAddress().toIpPort() << " is " << (conn->connected() ? "UP" : "DOWN");}void onMessage(const muduo::net::TcpConnectionPtr& conn, muduo::net::Buffer* buf, muduo::Timestamp time){ muduo::string msg(buf->retrieveAllAsString()); LOG_INFO << conn->name() << " echo " << msg.size() << " bytes, " << "data received at " << time.toString(); conn->send(msg);}int main(){ LOG_INFO << "pid = " << getpid(); muduo::net::EventLoop loop; muduo::net::InetAddress listenAddr(2007); muduo::net::TcpServer server(&loop, listenAddr, "EchoServer"); server.setConnectionCallback( boost::bind(onConnection, _1)); server.setMessageCallback( boost::bind(onMessage, _1, _2, _3)); server.start(); loop.loop(); return 0;}
首先定义了两个callBack函数,这两个函数要有一定格式(传入参数和返回值类型),具体格式定义了Callbacks.h中。onConnection在连接到来时调用,onMessage在消息到来时调用,(具体怎么调用后面解释)。
在main函数首先定了EventLoop对象和TcpServer对象。在定义TcpServer时不仅仅绑定了端口,还传入了EventLoop对象的指针,在TcpServer中保存着EventLoop对象的指针,EventLoop指针只能在TcpServer初始化时指定,后面不能更改。TcpServer在构造函数中还绑定了新连接到来时调用的回调函数,用来处理accept返回的fd(这个绑定其实是Acceptor绑定TcpServer的函数)。
之后,TcpServer对象server设置了回调函数,这两个函数分别在连接建立和消息到达时调用。
调用server.start()时,会初始化server对象中的threadPool_(用来给后面新建连接使用),随后把listen函数放入到loop函数对象容器中(如果在同一个线程则会立即执行,否则在下一次执行完IO事件后执行listen)。listen封装在Acceptor类中,Acceptor在TcpServer创建时创建,也包含了EventLoop对象指针,还包含了channel类。在Acceptor对象初始化时会创建channel类对象且将其加入到EventLoop的监听事件集合中,当有连接到来时,回调函数为void Acceptor::handleRead,在回调函数中,接受新连接,并调用newConnectionCallback_(即TcpServer::newConnection),接收新连接(保存为TcpConnection)并设置新连接回调函数,将新连接加入到另一个EventLoop中,在这个EventLoop中处理接收和发送。
以上大概就是Echo服务器的流程。
- muduo整体介绍及Echo服务器流程分析
- android呼叫流程分析--整体介绍
- 初识muduo:实现一个echo服务器
- muduo源码分析2:整体框架
- RxJava2_整体流程分析
- 使用muduo库编写回射服务器echo
- 大数据分析整体技术流程及架构
- muduo库的源代码分析1--整体架构
- dicom协议研究之echo流程分析
- Tomcat源码解析-整体流程介绍
- Tomcat源码解析-整体流程介绍2
- GDM图形界面登录整体流程分析
- 机房收费文档之流程整体分析
- 手势识别的整体流程分析
- MapReduce作业运行流程整体分析
- HDFS源码分析DataXceiver之整体流程
- DWR整体流程分析(转)
- input子系统整体流程全面分析
- 安全驾驶-喇叭(十三)
- 从勾画轮廓边深入三角网格邻接信息
- 如何设置Fedora默认从命令行启动
- 安全驾驶-远离大车(十四)
- HDU 1009 FatMouse' Trade
- muduo整体介绍及Echo服务器流程分析
- [LeetCode]232.Implement Queue using Stacks
- java 二进制(原码 反码 补码),位运算,移位运算,约瑟夫问题
- ubuntu 13.10下安装curl
- 安全驾驶-超车(十五)
- Android 自定义下拉刷新ExpandableListView
- C# 根据KeyEventArgs与组合键字符串相互转换
- 解决Android Studio Import Sample网络连接失败问题
- SpringMVC注解