详细muduo的使用(一)——源码分析(架构和概念)

本文介绍了陈硕开发的C++网络编程库muduo,详细解析了其基于Reactor模式的架构,包括连接建立、消息读取、发送的流程,以及连接断开、runInLoop的实现细节。文章通过分析muduo的线程模型,展示了主从reactor模式和业务线程池的概念,强调了线程安全和事件循环的重要性。
摘要由CSDN通过智能技术生成

 

目录

 

Muduo是什么?

muduo的架构和概念

一个简单的例子

连接的建立

消息的读取

消息的发送

为什么要移除可写事件

连接的断开

runInLoop的实现

为什么要唤醒EventLoop

wakeup是怎么实现的

doPendingFunctors的实现

muduo的线程模型

主从reactor模式

业务线程池

总结

参考


Muduo是什么?

muduo陈硕大神个人开发的C++的TCP网络编程库。muduo基于Reactor模式实现。Reactor模式也是目前大多数Linux端高性能网络编程框架和网络应用所选择的主要架构,例如内存数据库Redis和Java的Netty库等。

陈硕的《Linux多线程服务器端编程》一书对muduo整个架构进行了非常详尽的介绍和分析,可以说是学习muduo源码和设计理念最好的资料了。这本书也非常推荐大家购买阅读,感觉是后台开发的必读书目了。

而本文则主要是从源码角度辅助理解整个muduo的实现,同时也姑且算是对muduo的一个小小的补充。

同时提供了一个muduo注释版,以辅助大家参考学习。

muduo的架构和概念

muduo中类的职责和概念划分的非常清晰,在《Linux多线程服务器端编程》一书的6.3.1章节有详细的介绍。实际上目前很多网络库的接口设计也都受到了muduo的影响,例如360的evpp等。

经典的服务器设计模式Reactor模式

大多数人学习Linux网络编程的起点可能都是从《UNP》开始的,书中描述的服务端程序架构基本上是一个大的while循环,程序阻塞在accept或poll函数上,等待被监控的socket描述符上出现预期的事件。事件到达后,accept或poll函数的阻塞解除,程序向下执行,根据socket描述符上出现的事件,执行read、write或错误处理。 
整体架构如下图所示: 
 

而muduo的整体风格受到netty的影响,整个架构依照Reactor模式,基本与如下图所示相符:

                                                                              single_thread_reactor.png

所谓Reactor模式,是有一个循环的过程,监听对应事件是否触发,触发时调用对应的callback进行处理。

这里的事件在muduo中包括Socket可读写事件、定时器事件。在其他网络库中如libevent也包括了signal、用户自定义事件等。

负责事件循环的部分在muduo命名为EventLoop,其他库如netty、libevent也都有对应的组件。

负责监听事件是否触发的部分,在muduo中叫做Poller。muduo提供了epoll和poll两种来实现,默认是epoll实现。

通过环境变量MUDUO_USE_POLL来决定是否使用poll:

Poller* Poller::newDefaultPoller(EventLoop* loop)
{
  // 通过此环境变量来决定使用poll还是epoll
  if (::getenv("MUDUO_USE_POLL"))
  {
    return new PollPoller(loop);
  }
  else
  {
    return new EPollPoller(loop);
  }
}

此外,图中的acceptor负责accept新连接,并将新连接分发到subReactor。这个组件在muduo中也叫做Acceptor

关于图中的其他部分,会在muduo的线程模型一节有详细介绍。

一个简单的例子

本文首先从最简单的echo server入手,来介绍muduo的基本使用,同时也方便后面概念的理解。

void onMessage(const muduo::net::TcpConnectionPtr& conn,
                           muduo::net::Buffer* buf,
                           muduo::Timestamp time)
{
  conn->send(buf);
}

int main()
{
    muduo::net::EventLoop loop;//建立一个事件循环器EventLoop
    muduo::net::InetAddress listenAddr(2007);
    TcpServer server(&loop, listenAddr);//建立对应的业务服务器TcpServer
    server.setMessageCallback(onMessage);//设置TcpServer的Callback
    server.start();//启动server
    loop.loop();//开启事件循环
}

echo-server的代码量非常简洁。一个典型的muduo的TcpServer工作流程如下:

  1. 建立一个事件循环器EventLoop
  2. 建立对应的业务服务器TcpServer
  3. 设置TcpServer的Callback
  4. 启动server
  5. 开启事件循环

陈硕认为,TCP网络编程的本质是处理三个半事件,即:

  1. 连接的建立
  2. 连接的断开:包括主动断开和被动断开
  3. 消息到达,文件描述符可读。
  4. 消息发送完毕。这个算半个事件。
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值