1.源码阅读说明
-
本人是在具有C++基础和Linux系统与网络编程基础的情况下阅读muduo源码,如果对Linux网络编程不熟悉,最好先学习一下Linux网络编程
-
阅读时可以参考<muduo网络库使用手册>,这个一搜就能搜到,对muduo整体的框架有讲解,能帮助理解Buffer,TcpConnection等类,可以先读读这个再看源码
-
这里写的代码阅读笔记,只是对阅读源码的辅助,对各个类的功能和各函数难理解的地方做一些注释讲解,可以完全按照本人的阅读顺序,从base–>net–>httpserver–>example文件夹顺序阅读,每个文件夹里面的都按照顺序阅读,结合我自身的经验是循序渐进的阅读学习.下面是CSDN博客目录,推荐按如下顺序阅读:
- 2.muduo学习笔记之base_Timestamp.{h&cc}
- 3.muduo学习笔记之base_Atomic.{h&cc}
- 4.muduo学习笔记之base_Exception.{h&cc}
- 5.muduo学习笔记之base_Mutex.{h&cc}
- 6.muduo学习笔记之base_Condition.{h&cc}
- 7.muduo学习笔记之base_CountDownLatch.{h&cc}
- 8.muduo学习笔记之base_CurrentThread.{h&cc}
- 9.muduo学习笔记之base_Thread.{h&cc}
- 10.muduo学习笔记之base_BlockingQueue.{h&cc}
- 11.muduo学习笔记之base_BoundedBlockingQueue.{h&cc}
- 12.muduo学习笔记之base_ThreadPool.{h&cc}
- 13.muduo学习笔记之base_Singleton.{h&cc}
- 14.muduo学习笔记之base_ThreadLocal.{h&cc}
- 15.muduo学习笔记之base_ThreadLocalSingleton.{h&cc}
- 16.muduo学习笔记之base_LogStream.{h&cc}
- 17.muduo学习笔记之base_Logging.{h&cc}
- 18.muduo学习笔记之base_FileUtil.{h&cc}
- 19.muduo学习笔记之base_LogFile.{h&cc}
- 20.muduo学习笔记之base_其他.{h&cc}
- 21.muduo学习笔记之net_Callback.{h&cc}
- 22.muduo学习笔记之net_Endian.{h&cc}
- 23.muduo学习笔记之net_InetAddress.{h&cc}
- 24.muduo学习笔记之net_SocketsOps.{h&cc}
- 25.muduo学习笔记之net_Socket.{h&cc}
- 26.muduo学习笔记之net_Timer.{h&cc}
- 27.muduo学习笔记之net_TimerId.{h&cc}
- 28.muduo学习笔记之net_TimerQueue.{h&cc}
- 29.muduo学习笔记之net_EventLoop.{h&cc}
- 30.muduo学习笔记之net_Channel.{h&cc}
- 31.muduo学习笔记之net_EventLoopThread.{h&cc}
- 32.muduo学习笔记之net_Acceptor.{h&cc}
- 33.muduo学习笔记之net_TcpConnection.{h&cc}
- 34.muduo学习笔记之net_TcpServer.{h&cc}
- 35.muduo学习笔记之net_EventLoopThreadPool.{h&cc}
- 36.muduo学习笔记之net_Buffer.{h&cc}
- 37.muduo学习笔记之net_Connector.{h&cc}
- 38.muduo学习笔记之net_TcpClient.{h&cc}
- 39.muduo学习笔记之net_Poller.{h&cc}
- 40.muduo学习笔记之net_PollPoller.{h&cc}
- 41.muduo学习笔记之net_EPollPoller.{h&cc}
- 42.muduo学习笔记之http_HttpRequest.{h&cc}
- 43.muduo学习笔记之http_HttpResponse.{h&cc}
- 44.muduo学习笔记之http_HttpContext.{h&cc}
- 45.muduo学习笔记之http_HttpServer.{h&cc}
- 46.muduo学习笔记之example_discard例子
- 47.muduo学习笔记之example_下载文件例子
- 48.muduo学习笔记之example_聊天服务器例子
2. muduo安装使用
- 这里讲一下muduo如何使用,可以先运行一下再看源码,也可以看完源码在来使用…我是看完源码才用的,使用中也对源码整个框架有了更好的理解
1. 下载编译
-
muduo在github上有开源代码,作者也写的有README介绍如何运行,但是还是有些不理想,这里结合自身经历更详细的说一下如何编译安装
-
首先从muduo(github)下载源码,解压
-
进入解压的文件夹运行bash文件
./build.sh
- 会在上一层目录多个build文件夹,进去后的bin文件夹内都是作者写好的测试例子程序,可以直接运行
2. 使用
-
作者的README就是到上面这一步,但是这样只能运行测试作者写好的例子,想自己写代码使用的话,需要继续运行
./bulid.sh install
- 这样会在build文件夹内生成一个"release-install-cpp11"文件夹,里面是头文件和静态库,编译的时候就要指定链接库
-
可以参考作者陈硕的教程,这里有一个echo.cc服务例子和几种编译方法,我只关注了makefile文件,直接make不行,需要做一些修改
-
可以把echo.cc文件放到上面说的"release-install-cpp11"目录下,然后通过下面的命令编译
g++ echo.cc -I ./include -L ./lib -lmuduo_net -lmuduo_base -lpthread
- 这个本质就是要指定头文件和库文件所在位置,都在本目录下的include和lib文件夹下,如果在其他地方写程序,也需要指定这两个文件夹的目录,也可以放到系统path指定的目录中…
-
自己的代码要使用muduo的话,就需要这个include和lib文件夹,我为了方便使用就把这两个文件夹内的内容移动到了/usr/local/include和/usr/local/lib目录下,这样编译的时候就不用指定目录了
-
编程方面,主要是写三个回调函数,也就是关注作者所说的三个半事件
- onMessage() 当消息到来(1)时做什么
- onConnection() 当连接建立(2)和断开(3)的时候做什么
- onWriteComplete() 当写完后(第三个半事件)做什么
3. muduo各类总览
- 这个实际是摘抄<muduo网络库使用手册>中的部分内容,能帮助快速理解muduo类
1. 内部实现类
- Channel
- 是selectable IO channel,负责注册与响应IO事件,它不拥有file descriptor.它是Acceptor,Connector,EventLoop,TimeQueue,TcpConnection的成员,生命周期由后者控制
- Socket
- 封装一个file descriptor,并在析构的时候关闭fd.它是Acceptor,TcpConnection的成员,生命期由后者控制.EventLoop,TimerQueue也拥有fd,但是不封装为Socket.
- SocketsOps
- 封装各种sockets系统调用
- Poller
- 是PollPoller和EPollPoller的基类,采用"电平触发"的语意.它是EventLoop的成员,生命期由后者控制.
- PollPoller,EPollPoller
- 这两个封装poll(2)和epoll(4)两种IO Multiplexing后端.Poll的存在价值是便于调试,因为poll(2)调用是上下文无关的,用strace(1)很容易知道库的行为是否准确.
- Connector
- 用于发起TCP连接,它是TcpClient的成员,生命期由后者控制.
- Acceptor
- 用于接受TCP连接,它是TcpServer的成员,生命期由后者控制.
- TimerQueue
- 用timerfd实现定时,这有别于传统的设置poll/epoll_wait的等待时长的方法.TimerQueue用std::map来管理Timer,常用操作的复杂度是O(lnN),N为定时器数目.它是EventLoop的成员,生命期由后者控制.
- EventLoopThreadPool
- 用于创建IO线程池,用于把TcpConnection分派到某个EventLoop线程上.它是TcpServer的成员,生命期由后者控制.
2. 公开接口类
- Buffer
- 仿Netty ChannelBuffer的buffer class,数据的读写透过buffer进行.用户代码不需要调用read(2)/write(2),只需要处理收到的数据和准备好要发送的数据.
- InetAddress
- 封装IP地址,muduo目前不能解析域名,只认IP地址
- EventLoop
- 事件循环(反应器Reactor),每个线程只能有一个EventLoop实体,它负责IO和定时器事件的分派.它用eventfd(2)来异步唤醒,者有别于传统的用一对pipe(2)的办法.它用TimerQueue作为计时器管理,用Poller作为IO Multiplexing.
- EventLoopThread
- 启动一个线程,在其中运行EventLoop::loop().
- TcpConnection
- 整个网络库的核心,封装一次TCP连接
- TcpClient
- 用于编写网络客户端,能发起连接,并且有重试功能
- TcpServer
- 用于编写网络服务端,接受客户的连接
- 在这些类中,TcpConnection的生命期依靠share_ptr管理(即用户和库共同控制),Buffer的生命期由TcpConnection控制.其余类的生命期由用户控制.Buffer和InetAddress具有值语义,可以拷贝;其他class都是对象语义,不可以拷贝.
3. 类图
- 白三角表示继承,图中的Poller和PollPoller,EPollPoller的关系
- 白菱形表示聚合,菱形指向整体,部分能脱离整体存在
- 黑菱形表示组合,菱形指向整体,部分不能脱离整体存在
- 实现表示关联,一个类知道另一个类的属性和方法