muduo总结

总结说的有的过大,算是对自己学习的一个总结,后续会不断补充。

模型总结

muduo是基于非阻塞的IO和事件驱动的网络库。

muduo的整体结构时one loop per thread+threadpool,图如下:

mainReactor和subReactor都是EventLoop,在mainReactor中接收连接,把建立后的连接分发到subReactor中。

作者开始在muduo/base中封装了和网络无关的一些操作,如日志、时间、队列、互斥量、条件变量、线程、线程池等,给后面网络库的设计带来了极大便利。

在muduo/net中封装了和网络相关的操作,muduo是基于Reactor模式的设计的,结构如下:

1、EventLoop是整个模式的核心,它来管理所有事件。one loop per thread说明一个线程只能有一个EventLoop。它封装了eventfd和timerfd,用来唤醒等待在poll上的线程;eventfd是其他线程唤醒当前线程使用,把任务添加到EventLoop的任务队列后,如果不是EventLoop的owner线程,则要唤醒它来执行任务;timerfd用来实现定时。

2、Poller是个虚基类,真正调用的时PollPoller或EPollPoller。用来实现IO的复用,事件都注册到Poller中。

3、Channel和fd一一对应,虽然它不拥有fd,fd需要响应哪些事件都保存在Channel中,且有对应的回调函数。

4、TcpConnection是保存已经建立的连接,它的生命周期模式,因此采用shared_ptr来管理。它负责数据的发送和接收,负责socket fd的关闭。

5、Acceptor主要负责连接的建立,用在服务端。当建立连接后,它会把连接的控制权转交给TcpConnection。

6、TcpServer是服务端,有Acceptor,用Map保存了当前已经连接的TcpConnection。

7、Connector是负责发起连接的一方,用在客户端。发起连接比接收连接要难,非阻塞发起连接更难,要处理各种错误,还要考虑连接失败后如何处理。当连接成功后它会把控制权交给TcpConnection。

8、TcpClient是客户端,封装了Connector。

技术总结

muduo网络库虽然是用C++编写,但是却没有用到面向对象,用的是基于对象。最大的特点就是到处可见boost::bind,采用绑定回调函数的手法,实现了事件和特定函数的绑定,更加易于理解和使用。

对象生命周期的管理使用了shared_ptr。多线程中,对象的声明周期难以管理,一个线程难以判断对象是否已经析构,作者shared_ptr来管理对象声明周期。使用weak_ptr防止对象间相互引用,造成内存永久不释放。对于类内部的一些对象,使用scoped_ptr来管理。

非阻塞网络库应用层为什么需要缓冲区,怎么设计缓冲区。发送过快,缓冲区增长太大怎么办。

只使用非递归的互斥量,编码逻辑相对简单。

使用前置声明减少.h文件的包含。

……待续

版权声明:本文为博主原创文章,未经博主允许不得转载。

时间: 2024-10-12 18:32:09

muduo总结的相关文章

muduo::thread类分析

在看源代码前,先学习一个关键字:__thread. 线程共享进程的数据,如果想要每个线程都有一份独立的数据,那么可以使用__thread关键字修饰数据. __thread只能用于修饰POD类型的数据,不能修饰class,因为它无法调用构造函数和析构函数.__thread可以修饰全局变量.函数内的静态变量,不能修饰函数内的局部变量或class的普通成员变量. 在muduo/base/thread.{h, cc}中实现了线程的封装.thread的封装和一个命名空间muduo::CurrentThre

学习之前,先讲解下各种服务器模型,还有muduo的服务器模型

方案0:accept+read/write,阻塞,一次服务一个客户. 方案1:accept+fork,阻塞,采用多进程,长连接,并发性低,开销高,process-per-connection 方案2:accept+thread,阻塞,采用多线程,长连接,并发性中,开销中,多连接互通,thread-per-connection. 方案3:prefork,方案2的变形. 方案4:prethread,方案3的变形. // 开始采用I/O复用 方案5:poll(reactor),无阻塞,并发性高,开销低

Muduo网络库实战(二):实现服务器与客户端的连接

1. 方案的确定 1)基本需求 用户1000+, IO压力不大: 多个客户端打开网站,输入查询字符串strclient,发送给服务器=>服务器接收客户端发过来的数据并处理,将结果返回给客户端: 2)并发网络服务程序设计方案 详见:<Muduo_网络库使用手册>的1.6节-<详解Muduo多线程模型> @ muduo中TcpServer模式的选择:多线程模式 模式一:单线程,accept与TcpConnection用同一个线程做IO; 模式二:多线程,accept与EventL

Muduo阅读笔记

第一步:下载源码和文档 下载muduo项目的源码.<muduo-manual.pdf>文档,以及<Linux多线程服务端编程:使用muduo C++网络库.pdf>,这些是前期准备工作,都能在网上下载. 网站:http://www.chenshuo.com/ 第二步:先看看muduo-manual 在1.2节中,先将环境设置好.其中涉及到CMake和Boost:需要对这两个东西有一点了解,自行google或者百度这两个东西. 注意: 在编译muduo库的过程中输入./build.s

Muduo网络库源码分析(五)Acceptor和TcpServer类

首先,我们先提一下对Socket的封装(不复杂,所以简单说一下). Endian.h : 封装了字节序转换函数(全局函数,位于muduo::net::sockets名称空间中). SocketsOps.h/ SocketsOps.cc :封装了socket相关系统调用. Socket.h/Socket.cc(Socket类): 用RAII方法封装socket file descriptor. InetAddress.h/InetAddress.cc(InetAddress类):网际地址socka

Muduo网络库源码分析(一) EventLoop事件循环(Poller和Channel)

从这一篇博文起,我们开始剖析Muduo网络库的源码,主要结合<Linux多线程服务端编程>和网上的一些学习资料! (一)TCP网络编程的本质:三个半事件 1. 连接的建立,包括服务端接受(accept) 新连接和客户端成功发起(connect) 连接.TCP 连接一旦建立,客户端和服务端是平等的,可以各自收发数据. 2. 连接的断开,包括主动断开(close 或shutdown) 和被动断开(read(2) 返回0). 3. 消息到达,文件描述符可读.这是最为重要的一个事件,对它的处理方式决定

muduo Dispatcher消息分发器 通过多态和模板进行向上类型转换

所谓消息分发(muduo 中,就是接收到buffer之后,额,或者说是 protobuf),在简单的程序设计里面的话,估计就是 type-switch 了,但是这样的话,肯定就不好扩展维护啦. 最后的方法就是,可以根据 type-name 自动去调用相应的方法. typedef boost::function<void (Message*)> ProtobufMessageCallback; 这个算是一个映射咯.muduo 中采用的是 map<Descriptor*,ProtobufMe

muduo::Connector、TcpClient分析

Connector TcpClient Connector Connector用来发起连接.在非阻塞网络中,主动发起连接比被动接收连接更为复杂,因为要考虑错误处理,还要考虑重试. 主要难点在于 1.socket是一次性的,一旦出错无法恢复:只能关闭重来.使用新的fd后,用新的channel. 2.错误代码与acce(2)不同.及时是socket可写,也不意味着已经成功建立连接,还需要用getsockopt(sockfd, SOL_SOCKET, SO_ERROR, --)再次确认. 3.重试的间

muduo::TcpConnection分析

TcpConnection是使用shared_ptr来管理的类,因为它的生命周期模糊.TcpConnection表示已经建立或正在建立的连接,状态只有kConnecting.kConnected.kDisconnected.kDisconnecting,它初始化时,构造函数的sockfd表示正在建立连接kConnecting. 建立连接后,用户只需处理收发数据,发送数据它会自动处理,收取数据后,会调用用户设置的MessageCallback函数来处理收到的数据. TcpConnection中封装

muduo::EventLoopThread、EventLoopThreadPool分析

EventLoopThread EventLoopThreadPool muduo的并发模型为one loop per thread+ threadpool.为了方便使用,muduo封装了EventLoop和Thread为EventLoopThread,为了方便使用线程池,又把EventLoopThread封装为EventLoopThreadPool. EventLoopThread 任何一个线程,只要创建并运行了EventLoop,就是一个IO线程. EventLoopThread类就是一个封