Muduo 网络库使用手册 by 陈硕
1
Muduo 网络库使用手册
陈硕 (giantchen@gmail.com)
最后更新 2012-6-26
版权声明
本作品采用“Creative Commons 署名 -非商业性使用 -禁止演绎 3.0 Unported 许可
协议 (cc by-nc-nd)”进行许可。http://creativecommons.org/licenses/by-nc-nd/3.0/
内容一览
1 Muduo 网络库简介
1.1 由来 . .
1.2 安装 . .
.
.
.
.
.
.
1.3 目录结构 . .
1.4 使用教程 . .
1.5 性能评测 . .
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
. .
. .
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
1.6 详解 Muduo 多线程模型 .
2 Muduo 编程示例
2.1 五个简单 TCP 协议 . .
2.2 文件传输 . .
.
.
.
.
.
.
.
.
.
.
2.3 Boost.Asio 的聊天服务器 .
2.4 Buffer 类的设计与使用 .
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
. .
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
2.5 一种自动反射消息类型的 Google Protobuf 网络传输方案 . .
2.6 在 muduo 中实现 Protobuf 编解码器与消息分发器 .
2.7 限制服务器的最大并发连接数 . .
2.8 定时器 .
.
.
.
.
.
.
.
.
.
.
2.9 测量两台机器的网络延迟 .
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
. .
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
3
3
4
6
.
.
.
. 13
. 22
.
.
.
.
.
. .
35
49
.
.
. 50
. 57
. .
.
.
.
.
.
.
.
66
76
91
. 100
. 108
. 112
. . 119
www.chenshuo.com
Muduo 网络库简介 by 陈硕
2
2.10 用 Timing wheel 踢掉空闲连接 .
2.11 简单的消息广播服务 . .
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
. .
.
2.12 “串并转换”连接服务器及其自动化测试 .
2.13 socks4a 代理服务器 . .
2.14 短址服务 . .
.
.
2.15 与其他库集成 .
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
. .
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
. .
.
.
.
.
.
.
.
.
.
.
.
.
. 122
. 128
. 131
. 136
. 139
. 140
www.chenshuo.com
1
Muduo 网络库简介
1.1 由来
2010 年 3 月我写了一篇《学之者生,用之者死——ACE 历史与简评》1 ,其中提
到“我心目中理想的网络库”的样子:
• 线程安全,原生支持多核多线程
• 不考虑可移植性,不跨平台,只支持 Linux,不支持 Windows。
• 主要支持 x86-64,兼顾 IA32。(实际上 muduo 也可以运行在 ARM 上。)
• 不支持 UDP,只支持 TCP。
• 不支持 IPv6,只支持 IPv4。
• 不考虑广域网应用,只考虑局域网。(实际上 muduo 也可以用在广域网上。)
• 不考虑公网,只考虑内网。不为安全性做特别的增强。
• 只支持一种使用模式:non-blocking IO + one event loop per thread,不支持阻
塞 IO。
• API 简单易用,只暴露具体类和标准库里的类。API 不使用 non-trivial tem-
plates,也不使用虚函数。
• 只满足常用需求的 90%,不面面俱到,必要的时候以 app 来适应 lib。
• 只做 library,不做成 framework。
• 争取全部代码在 5000 行以内(不含测试)。(目前 muduo 网络部分的核心代码
约 4400 行。)
• 在不增加复杂度的前提下可以支持 FreeBSD/Darwin,方便将来用 Mac 作为
开发用机,但不为它做性能优化。也就是说 IO multiplexing 使用 poll(2) 和
epoll(4)。
1http://blog.csdn.net/Solstice/archive/2010/03/10/5364096.aspx
3
Muduo 网络库简介 by 陈硕
4
• 以上条件都满足时,可以考虑搭配 Google Protocol Buffers RPC
在想清楚这些目标之后,我开始第三次尝试编写自己的 C++ 网络库。与前两次
不同,这次我一开始就想好了库的名字,叫 muduo (木铎),并在 Google code 上
创建了项目:http://code.google.com/p/muduo/。Muduo 以 git 为版本管理工具,
托管于 https://github.com/chenshuo/muduo。muduo 的主体内容在 2010 年 5 月
底已经基本完成,8 月底发布 0.1.0 版,现在(2012 年 6 月)的最新版本是 0.7.0。
1.2 安装
源文件 tar 包的下载地址:http://code.google.com/p/muduo/downloads/list,
此处以 muduo-0.7.0-beta.tar.gz 为例。
Muduo 使用了 Linux 较新的系统调用 2,要求 Linux 的内核版本大于 2.6.28。
我自己用 Debian 6.0 Squeeze / Ubuntu 10.04 LTS 作为主要开发环境(内核版本
2.6.32),以 g++ 4.4 为主要编译器版本,在 32 位和 64 位 x86 系统都编译测试通过。
Muduo 在 Fedora 13 和 CentOS 6 上也能正常编译运行,还有热心网友为 Arch Linux
编写了 AUR 文件 3。
如果要在较旧的 Linux 2.6 内核 4 上使用 muduo,可以参考 backport.diff 来修
改代码。不过这些系统上没有充分测试,仅仅是编译和冒烟测试通过。另外 muduo
也可以运行在嵌入式系统中,我在 Samsung S3C2440 开发板(ARM9)上成功运行
了 muduo 的多个示例。当时 Linux 内核版本为 2.6.32,代码需略作改动,请参考
armlinux.diff。
Muduo 采用 CMake 5 为 build system,安装方法:
$ sudo apt-get install cmake
Muduo 依赖 Boost 6,很容易安装:
$ sudo apt-get install libboost1.40-dev
或
$ sudo apt-get install libboost1.42-dev
2主要是 timerfd 和 eventfd。
3http://aur.archlinux.org/packages.php?ID=49251
4例如 Debian 5.0 Lenny、Ubuntu 8.04、CentOS 5 等等发行版。
5最好不低于 2.8 版,CentOS 6 自带的 2.6 版也能用,但是无法自动识别 Protobuf 库。
6核心库只依赖 TR1,示例代码用到了其他 boost 库
www.chenshuo.com
Muduo 网络库简介 by 陈硕
5
muduo 有三个非必须的依赖库:curl、c-ares DNS、Google Protobuf,如果安装了
这三个库,cmake 会自动多编译一些示例。
$ sudo apt-get install libcurl4-openssl-dev libc-ares-dev
$ sudo apt-get install protobuf-compiler libprotobuf-dev
编译方法很简单:
$ tar zxf muduo-0.7.0-beta.tar.gz
$ cd muduo/
$ ./build.sh -j2
编译 muduo 库和它自带的例子,生成的可执行文件和静态库文件
分别位于 ../build/debug/{bin,lib}
$ ./build.sh install
以上命令将 muduo 头文件和库文件安装到 ../build/debug-install/{include,lib}
如果要编译 release 版(以 -O2 优化),可执行
$ BUILD_TYPE=release ./build.sh -j2
编译 muduo 库和它自带的例子,生成的可执行文件和静态库文件
分别位于 ../build/release/{bin,lib}
$ BUILD_TYPE=release ./build.sh install
以上命令将 muduo 头文件和库文件安装到 ../build/release-install/{include,lib}
在 muduo 1.0 正式发布之后,BUILD_TYPE 的默认值会改成 release。
编译完成之后请试运行其中的例子。比如 bin/inspector_test ,然后通过浏览器
访问 http://10.0.0.10:12345/ 或 http://10.0.0.10:12345/proc/status,其中 10.0.0.10
替换为你的 Linux box 的 IP。
1.2.1 在自己的程序中使用 muduo
Muduo 是静态链接 7 的 C++ 程序库,使用 muduo 库的时候,只需要设置好头文
件路径(例如../build/debug-install/include)和库文件路径(例如../build/debug-
install/lib)并链接相应的静态库文件(-lmuduo_net -lmuduo_base)即可。下面这
个示范项目展示了如何使用 CMake 和普通 make 编译基于 muduo 的程序
https://github.com/chenshuo/muduo-tutorial。
7原因是在分布式系统中正确安全地发布动态库的成本很高,见第 ?? 章。
www.chenshuo.com
Muduo 网络库简介 by 陈硕
1.3 目录结构
Muduo 的目录结构如下。
6
muduo
|-- build.sh
|-- ChangeLog
|-- CMakeLists.txt
|-- License
|-- README
|-- muduo
|
|
|
|
|
|
|-- examples
\-- TODO
|-- base
\-- net
muduo 库的主体
与网络无关的基础代码,位于 ::muduo namespace,包括线程库
网络库,位于 ::muduo::net namespace
poll(2) 和 epoll(4) 两种 IO multiplexing 后端
一个简单的可嵌入的 web 服务器
基于以上 web 服务器的“窥探器”,用于报告进程的状态
|-- poller
|-- http
|-- inspect
\-- protorpc 简单实现 Google Protobuf RPC,不推荐使用
丰富的示例
Muduo 的 源 代 码 文 件 名 与 class 名 相 同,例 如 ThreadPool class 的 定 义 是
muduo/base/ThreadPool.h,其实现位于 muduo/base/ThreadPool.cc。
基础库
muduo/base 目录是一些基础库,都是用户可见的类,内容包括
muduo
\-- base
|-- AsyncLogging.{h,cc}
|-- Atomic.h
|-- BlockingQueue.h
|-- BoundedBlockingQueue.h
|-- Condition.h
|-- copyable.h
|-- CountDownLatch.{h,cc}
|-- Date.{h,cc}
|-- Exception.{h,cc}
|-- Logging.{h,cc}
|-- Mutex.h
|-- ProcessInfo.{h,cc}
|-- Singleton.h
|-- StringPiece.h
|-- tests
|-- Thread.{h,cc}
|-- ThreadLocal.h
|-- ThreadLocalSingleton.h
|-- ThreadPool.{h,cc}
异步日志 backend
原子操作与原子整数
无界阻塞队列(消费者生产者队列)
有界阻塞队列
条件变量,与 Mutex 一同使用
一个空基类,用于标识 (tag) 值类型
“倒计时门闩”同步
Julian 日期库(即公历)
带 stack trace 的异常基类
简单的日志,可搭配 AsyncLogging 使用
互斥器
进程信息
线程安全的 singleton
从 Google 开源代码借用的字符串参数传递类型
测试代码
线程对象
线程局部数据
每个线程一个 singleton
简单的固定大小线程池
www.chenshuo.com
Muduo 网络库简介 by 陈硕
7
|-- Timestamp.{h,cc}
|-- TimeZone.{h,cc}
\-- Types.h
UTC 时间戳
时区与夏令时
基本类型的声明,包括 muduo::string
网络核心库
Muduo 是基于 Reactor 模式的网络库,其核心是个事件循环 EventLoop,用于
响应计时器和 IO 事件。Muduo 采用基于对象(object based)而非面向对象(object
oriented)的设计风格,其事件回调接口多以 boost::function + boost::bind 表达,用
户在使用 muduo 的时候不需要继承其中的 class。
网络库核心位于 muduo/net 和 muduo/net/poller,一共不到 4300 行代码,以
下灰底表示用户不可见的内部类。
muduo
\-- net
|-- Acceptor.{h,cc}
|-- Buffer.{h,cc}
|-- Callbacks.h
|-- Channel.{h,cc}
|-- CMakeLists.txt
|-- Connector.{h,cc}
|-- Endian.h
|-- EventLoop.{h,cc}
|-- EventLoopThread.{h,cc}
|-- EventLoopThreadPool.{h,cc}
|-- InetAddress.{h,cc}
|-- Poller.{h,cc}
|-- poller
|
|
|
|-- Socket.{h,cc}
|-- SocketsOps.{h,cc}
|-- TcpClient.{h,cc}
|-- TcpConnection.{h,cc}
|-- TcpServer.{h,cc}
|-- tests
|-- Timer.{h,cc}
|-- TimerId.h
\-- TimerQueue.{h,cc}
|-- DefaultPoller.cc
|-- EPollPoller.{h,cc}
\-- PollPoller.{h,cc}
网络附属库
接受器,用于服务端接受连接
缓冲区,非阻塞 IO 必备
用于每个 Socket 连接的事件分发
连接器,用于客户端发起连接
网络字节序与本机字节序的转换
事件分发器
新建一个专门用于 EventLoop 的线程
Muduo 默认多线程 IO 模型
IP 地址的简单封装,
IO multiplexing 的基类接口
IO multiplexing 的实现
根据环境变量 MUDUO_USE_POLL 选择后端
基于 epoll(4) 的 IO multiplexing 后端
基于 poll(2) 的 IO multiplexing 后端
封装 Sockets 描述符,负责关闭连接
封装底层的 Sockets API
TCP 客户端
muduo 里最大的一个类,有 300 多行
TCP 服务端
简单测试
以下几个文件与定时器回调相关
网络库有一些附属模块,它们不是核心内容,在使用的时候需要链接相应的
库,例如 -lmuduo_http, -lmuduo_inspect 等等。HttpServer 和 Inspector 暴露出一
个 http 界面,用于监控进程的状态,类似于 Java JMX。见第 ?? 节。
www.chenshuo.com
Muduo 网络库简介 by 陈硕
8
附属模块位于 muduo/net/{http,inspect,protorpc} 等处。
muduo
\-- net
|-- CMakeLists.txt
|-- HttpContext.h
|-- HttpRequest.h
|-- HttpResponse.{h,cc}
|-- HttpServer.{h,cc}
\-- tests/HttpServer_test.cc 示范如何在程序中嵌入 http 服务器
|-- http 不打算做成通用的 http 服务器,这只是简陋而不完整 http 协议实现
|
|
|
|
|
|
|-- inspect
|
|
|
|
\-- protorpc
|-- CMakeLists.txt
|-- Inspector.{h,cc}
|-- ProcessInspector.{h,cc}
\-- tests/Inspector_test.cc 示范暴露程序状态,包括内存使用和文件描述符
基于 http 协议的窥探器,用于报告进程的状态
简单实现 Google Protobuf RPC
|-- CMakeLists.txt
|-- google-inl.h
|-- RpcChannel.{h,cc}
|-- RpcCodec.{h,cc}
|-- rpc.proto
\-- RpcServer.{h,cc}
1.3.1 代码结构
Muduo 的头文件明确分为客户可见和客户不可见两类。以下是安装之后暴露
的头文件和库文件。对于使用 muduo 库而言,只需要掌握 5 个关键类:Buffer、
EventLoop、TcpConnection、TcpClient、TcpServer。
头文件
基础库,同前,略
网络核心库
\-- muduo
|-- base
\-- net
|-- include
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|-- Buffer.h
|-- Callbacks.h
|-- Endian.h
|-- EventLoop.h
|-- EventLoopThread.h
|-- InetAddress.h
|-- TcpClient.h
|-- TcpConnection.h
|-- TcpServer.h
|-- TimerId.h
|-- http
|
|
|
|-- HttpRequest.h
|-- HttpResponse.h
\-- HttpServer.h
以下为网络附属库的头文件
www.chenshuo.com