本文主要介绍 muduo 网络库的使用。其设计与实现将有另文讲解。
目录
由来 1
下载与编译 2
例子 2
基本结构 3
公开接口 4
内部实现 4
线程模型 5
结语 5
由来
半年前我写了一篇《学之者生,用之者死——ACE历史与简评》,其中提到“我心目中理想的网络库”的样子:
线程安全,支持多核多线程
不考虑可移植性,不跨平台,只支持 Linux,不支持 Windows。
在不增加复杂度的前提下可以支持 FreeBSD/Darwin,方便将来用 Mac 作为开发用机,但不为它做性能优化。也就是说 IO multiplexing 使用 poll 和 epoll。
主要支持 x86-64,兼顾 IA32
不支持 UDP,只支持 TCP
不支持 IPv6,只支持 IPv4
不考虑广域网应用,只考虑局域网
只支持一种使用模式:non-blocking IO + one event loop per thread,不考虑阻塞 IO
API 简单易用,只暴露具体类和标准库里的类,不使用 non-trivial templates,也不使用虚函数
只满足常用需求的 90%,不面面俱到,必要的时候以 app 来适应 lib
只做 library,不做成 framework
争取全部代码在 5000 行以内(不含测试)
以上条件都满足时,可以考虑搭配 Google Protocol Buffers RPC
在想清楚这些目标之后,我开始第三次尝试编写自己的 C++ 网络库。与前两次不同,这次我一开始就想好了库的名字,叫 muduo (木铎),并在 Google code 上创建了项目: http://code.google.com/p/muduo/ 。muduo 的主体内容在 5 月底已经基本完成,现在我把它开源。
本文主要介绍 muduo 网络库的使用,其设计与实现将有另文讲解。
下载与编译
下载地址: http://muduo.googlecode.com/files/muduo-0.1.0-alpha.tar.gz
SHA1 Checksum: 5d3642e311177ded89ed0d15c10921738f8c984c
Muduo 使用了 Linux 较新的系统调用,要求 Linux 的内核版本大于 2.6.28 (我自己用的是 2.6.32 )。在 Debian Squeeze / Ubuntu 10.04 LTS 上编译测试通过,32 位和 64 位系统都能使用。
Muduo 采用 CMake 为 build system,安装方法:
$ sudo apt-get install cmake
Muduo 依赖 Boost,很容易安装:
$ sudo apt-get install libboost1.40-dev # 或 libboost1.42-dev
编译方法很简单:
$ tar zxf muduo-0.1.0-alpha.tar.gz
$ cd muduo/
$ ./build.sh
# 编译生成的可执行文件和静态库文件分别位于 ../build/debug/{bin,lib}
如果要编译 release 版,可执行
$ BUILD_TYPE=release ./build.sh
# 编译生成的可执行文件和静态库文件分别位于 ../build/release/{bin,lib}
编译完成之后请试运行其中的例子。比如 bin/inspector_test ,然后通过浏览器访问 http://10.0.0.10:12345/ 或 http://10.0.0.10:12345/proc/status,其中 10.0.0.10 替换为你的 Linux box 的 IP。
例子
Muduo 附带了几十个小例子,位于 examples 目录。其中包括从 Boost.Asio、JBoss Netty、Python Twisted 等处移植过来的例子。
examples
|-- simple # 简单网络协议的实现
| |-- allinone # 在一个程序里同时实现下面 5 个协议
| |-- chargen # RFC 864,可测试带宽
| |-- daytime # RFC 867
| |-- discard # RFC 863
| |-- echo # RFC 862
| |-- time # RFC 868
| `-- timeclient # time 协议的客户端
|-- hub # 一个简单的 pub/sub/hub 服务,演示应用级的广播
|-- roundtrip # 测试两台机器的网络延时与时间差
|-- asio # 从 Boost.Asio 移植的例子
| |-- chat # 聊天服务
| `-- tutorial # 一系列 timers
|-- netty # 从 JBoss Netty 移植的例子
| |-- discard # 可用于测试带宽,服务器可多线程运行
| |-- echo # 可用于测试带宽,服务器可多线程运行
| `-- uptime # TCP 长连接
`-- twisted # 从 Python Twisted 移植的例子
`-- finger # finger01 ~ 07
基本结构
Muduo 的目录结构如下。
muduo
|-- base # 与网络无关的基础代码,已提前发布
`-- net # 网络库
|-- http # 一个简单的可嵌入的 web 服务器
|-- inspect # 基于以上 web 服务器的“窥探器”,用于报告进程的状态
`-- poller # poll(2) 和 epoll(4) 两种 IO multiplexing 后端
Muduo 是基于 Reactor 模式的网络库,其核心是个事件循环 EventLoop,用于响应计时器和 IO 事件。Muduo 采用基于对象(object based)而非面向对象(object oriented)的设计风格,其接口多以 boost::function + boost::bind 表达。
Muduo 的头文件明确分为客户可见和客户不可见两类。客户可见的为白底,客户不可见的为灰底。
这里简单介绍各个头文件及 class 的作用,详细的介绍留给以后的博客。
公开接口
Buffer 仿 Netty ChannelBuffer 的 buffer class,数据的读写透过 buffer 进行
InetAddress 封装 IPv4 地址 (end point),注意,muduo 目前不能解析域名,只认 IP
EventLoop 反应器 Reactor,用户可以注册计时器回调
EventLoopThread 启动一个线程,在其中运行 EventLoop::loop()
TcpConnection 整个网络库的核心,封装一次 TCP 连接
TcpClient 用于编写网络客户端,能发起连接,并且有重试功能
TcpServer 用于编写网络服务器,接受客户的连接
在这些类中,TcpConnection 的生命期依靠 shared_ptr 控制(即用户和库共同控制)。Buffer 的生命期由 TcpConnection 控制。其余类的生命期由用户控制。
HttpServer 和 Inspector,暴露出一个 http 界面,用于监控进程的状态,类似于 Java JMX。这么做的原因是,《程序员修炼之道》第 6 章第 34 条提到“对于更大、更复杂的服务器代码,提供其操作的内部试图的一种漂亮技术是使用内建的 Web 服务器”,Jeff Dean 也说“(每个 Google 的服务器进程)Export HTML-based status pages for easy diagnosis”。
内部实现
Channel 是 selectable IO channel,负责注册与响应 IO 事件,它不拥有 file descriptor。它是 Acceptor、Connector、EventLoop、TimerQueue、TcpConnection 的成员,生命期由后者控制。
Socket 封装一个 file descriptor,并在析构时关闭 fd。它是 Acceptor、TcpConnection 的成员,生命期由后者控制。EventLoop、TimerQueue 也拥有 fd,但是不封装为 Socket。
SocketsOps 封装各种 sockets 系统调用。
EventLoop 封装事件循环,也是事件分派的中心。它用 eventfd(2) 来异步唤醒,这有别于传统的用一对 pipe(2) 的办法。它用 TimerQueue 作为计时器管理,用 Poller 作为 IO Multiplexing。
Poller 是 PollPoller 和 EPollPoller 的基类,采用“电平触发”的语意。它是 EventLoop 的成员,生命期由后者控制。
PollPoller 和 EPollPoller 封装 poll(2) 和 epoll(4) 两种 IO Multiplexing 后端。Poll 的存在价值是便于调试,因为 poll(2) 调用是上下文无关的,用 strace 很容易知道库的行为是否正确。
Connector 用于发起 TCP 连接,它是 TcpClient 的成员,生命期由后者控制。
Acceptor 用于接受 TCP 连接,它是 TcpServer 的成员,生命期由后者控制。
TimerQueue 用 timerfd 实现定时,这有别于传统的设置 poll/epoll_wait 的等待时长的办法。为了简单起见,目前用链表来管理 Timer,如果有必要可改为优先队列,这样复杂度可从 O(n) 降为O(ln n) (某些操作甚至是 O(1))。它是 EventLoop 的成员,生命期由后者控制。
EventLoopThreadPool 用于创建 IO 线程池,也就是说把 TcpConnection 分派到一组运行 EventLoop 的线程上。它是 TcpServer 的成员,生命期由后者控制。
类图
线程模型
Muduo 的线程模型符合我主张的 one loop per thread + thread pool 模型。每个线程最多有一个 EventLoop。每个 TcpConnection 必须归某个 EventLoop 管理,所有的 IO 会转移到这个线程,换句话说一个 file descriptor 只能由一个线程读写。TcpConnection 所在的线程由其所属的 EventLoop 决定,这样我们可以很方便地把不同的 TCP 连接放到不同的线程去,也可以把一些 TCP 连接放到一个线程里。TcpConnection 和 EventLoop 是线程安全的,可以跨线程调用。TcpServer 直接支持多线程,它有两种模式:
1. 单线程,accept 与 TcpConnection 用同一个线程做 IO。
2. 多线程,accept 与 EventLoop 在同一个线程,另外创建一个 EventLoopThreadPool,新到的连接会按 round-robin 方式分配到线程池中。
结语
Muduo 是我对常见网络编程任务的总结,用它我能很容易地编写多线程的 TCP 服务器和客户端。Muduo 是我业余时间的作品,代码估计还有很多 bug,功能也不完善(例如不支持 signal 处理),待日后慢慢改进吧。
后记:性能测试:
1. muduo 与 boost asio 吞吐量对比
2. muduo 与 libevent2 吞吐量对比
3. 击鼓传花:对比 muduo 与 libevent2 的事件处理效率
本文来自CSDN博客,转载请标明出处:http://blog.csdn.net/Solstice/archive/2010/08/29/5848547.aspx
分享到:
相关推荐
Easy-Reactor是一个基于Reactor模式的Linux C++网络服务器框架,支持多线程TCP服务器,单线程TCP服务器,单线程UDP服务器等形式,可以让使用者完全专注于业务,快速开发出一个高效的服务器应用。 在工作中开发基础...
C++的百宝箱,是一个完备的Linux应用l软件开发工具库与运行框架。 它有通信库(TCP/UDP/串口)、HTTP、线程池、定时器池、协程、日志、命令终端、状态机、行为树等非常实用的开发组件,它还有完备实用的启动框架。 ...
【项目资源】: 包含前端、后端、移动开发、操作系统、人工智能、物联网、信息化管理、数据库、硬件开发、大数据、课程资源、音视频、网站开发等各种技术项目的... 部分字体以及插图等来自网络,若是侵权请联系删除。
net是一个基于Reactor 模式的现代化C++11网络库。 自带TCP协议的异步非阻塞式的服务器和客户端库。 实现上深度借鉴和两个开源网络库。 性能上没太多测试,不过个人感觉性能还不错。。。 没啥第三方库依赖,只要支持...
muduo 是一个基于 Reactor 模式的现代 C++ 网络库,它采用非阻塞 IO 模型,基于事件驱动和回调,原生支持多核多线程,适合编写 Linux 服务端多线程网络应用程序
Chaos是一个基于Linux平台, reactor模式的网络事件库, 目前仅支持TCP传输协议, 仅在x86_64下编译, 并遵循3-clause BSD开源协议. 在使用上, 可以说它很像boost asio, 可能是由于我对boost asio的接口设计很有爱吧, ...
【项目资源】: 包含前端、后端、移动开发、操作系统、人工智能、物联网、信息化管理、数据库、硬件开发、大数据、课程资源、音视频、网站开发等各种技术项目的... 部分字体以及插图等来自网络,若是侵权请联系删除。
Herm是一套快速开发高性能的网络应用的C++库。比如开发网络游戏、即时通信、流媒体、文件下载、P2P等基于TCP/IP网络应用。 Herm包括三个组件: (1)Utilities 最基础的组件,提供线程、一读一写线程不加锁的...
tinyev是仿照muduo[1]实现的一个基于Reactor模式的多线程C++网络库,经过适当简化以后代码量约为2000行。简化的部分如下: 多线程依赖于C++11提供的std::thread库,而不是重新封装POSIX thread API。 定时器依赖于...
包括STM32、ESP8266、PHP、QT、Linux、iOS、C++、Java、python、web、C#、EDA、proteus、RTOS等项目的源码。 【项目质量】: 所有源码都经过严格测试,可以直接运行。 功能在确认正常工作后才上传。 【适用人群】...
是否具备高并发、高性能、分布式、事件驱动框架设计能力,是优秀C++中高级工程师的分水岭,我将通过本文带领大家纯手写一个Reactor服务器,让大家可以高效掌握三高框架设计思维,同时让你对C++网络编程、线程、智能...
Reactor 模式也叫做反应器设计模式,它是一种为处理服务请求并发提交到一个或者多个服务处理程序的事件设计模式。当请求抵达后,服务处理程序使用解多路分配策略,然后同步地派发这些请求至相关的请求处理程序。 ...
4.基于reactor模式的实现。 课程通过多角度、深层次的教学及实践,带领同学们进行C++企业级网络开发实战和Libevent C++跨平台高级实战技术课程的学习。课程通过八部分教学内容,进行层层剖析,将所有知识点的...
**1)主线程实现eventLoop**:主线程基于Reactor并通过Epoll管理,采用ET工作模式进行事件触发,事件注册包括监听、管道监控、读信息监控;\ **2)定时器处理非活动连接**:\ **①基于升序链表的定时器**:将每个...
基于Reactor模式,效率较高,并且代码精简(4.15版本8000多行),是学习事件驱动编程的很好的资源。 下载链接: Memcached Memcached 是一个高性能的分布式内存对象缓存系统,用于动态Web应用以减轻数据库负载。它...
EnvLinux version 5.3.0-28-genericgcc version 7.5.0Ubuntu 18.04.1cmake version 3.17.0Build ./build.shDescription 基于C++11、部分C++14/17特性的一个高性能并发网络服务器,包括目前已实现日志、线程池、...
C++工具 ibev-4.15 源码 libev是一个开源的事件驱动库,基于epoll,kqueue等OS提供的基础设施。其以高效出名,它可以将IO事件...基于Reactor模式,效率较高,并且代码精简(4.15版本8000多行),是学习事件驱动编程的很
项目是在Linux下以C++开发语言搭建的Web服务器,服务器可以支持相对数量的客户端并发和及时响应,该项目支持用户注册、登录,访问图片和视频。1.利用IO多路复用技术Epoll与线程池实现Reactor高并发模型。 2.利用主从...
React器模式下的MQTT Server 基于c ++ 0x11和accept4的简单React器使用log4cplus-1.1.2,使用静态lib链接。 可以看到include / reactor / define.hpp并从main.cpp中移动记录器定义 #定义HAS_LOG4CPLUSH_LOG #...