muduo网络库简介

  • 高级语言(Java, Python等)的Sockects库并没有对Sockects API提供更高层的封装, 直接用它编写程序很容易掉到陷阱中;
  • 网络库的价值还在于能方便地处理并发链接;

网络核心库

  • muduo是基于Reactor模式的网络库, 其核心是个事件循环EventLoop,用于响应计时器和IO事件;

    • muduo采用基于对象(object-based)而非面向对象(object-oriented)的设计风格;

网络附属库

  • 网络库有一些附属模块, 它们不是核心内容, 在使用的时候需要链接相应的库;
  • 使用muduo库而言, 只需要掌握5个关键类:Buffer,EventLoop, TcpConnection, TcpClient, TcpServer;

线程模型

  • muduo的线程模型符合one loop per thread + thread pool模型;

    • 每个线程最多有一个EventLoop, 每个TcpConnection必须归某个EventLoop管理, 所有的IO会转移到这个线程;
  • ThreadPool, 新到的链接会按round-robin方式分配到线程池中;
  • muduo库的核心是每个IO线程一个事件循环, 把IO事件分发到回调函数上;
  • 希望muduo库能减少网络编程中的偶发复杂性(accidental complexity);
  • 基于事件的非阻塞网络编程是编写高性能并发网络服务程序的主流模式;
    • 大量用到了回调函数的思想;
  • TCP网络编程最本质是处理三个半事件:
    • 连接的建立, 包括服务器端接受(accept)新链接和客户端成功发起(connect)链接; TCP连接一旦建立, 客户端和服务端是平等的, 可以各自收发数据;
    • 连接的断开, 包括主动断开(close, shutdown)和被动断开(read返回0);
    • 消息到达, 文件描述符可读; 这是最重要的一个事件, 对它的处理方式决定了网络编程的风格(阻塞还是非阻塞, 如何处理分包, 应用层的缓冲如何设计, 等等);
    • 消息发送完毕, 这个算半个; 对于低流量的服务, 可以不必关心这个事件; 另外, 这里的发送完毕是指数据写入操作系统的缓冲区, 将由TCP协议栈负责数据的发送与重传, 不代表对方已经收到了数据;
  • echo 服务器的实现:
    • muduo的使用非常简单, 不需要从指定的类派生, 也不用覆写虚函数, 只需要注册几个回调函数去处理三个半事件就行了;
    • echo服务器的业务逻辑就是把收到的数据原封不动地发回客户端;
    • 程序主体是被动等待事件发生, 事件发生之后网络库会调用(回调)事先注册的事件处理函数(event handler);
  • 七步实现finger服务
    • Python Twisted是一款非常好的网络库, 它也是采用的Reactor作为网络编程的基本模型, 所以从使用上与muduo颇有相似之处(muduo没有deferreds);
    • finger是Twisted文档中一个经典的例子, muduo来实现最简单的finger服务端;
      • 大佬的muduo学习笔记;
      • finger(端口79)是互连网上最古老的协议之一, 用于提供站点及用户的基本信息, 一般通过finger服务,你可以查询到站点上的在线用户清单及其他一些有用的信息;
      • finger服务是基于客户/服务器模式的,目标机上通常有一个fingerd的服务器程序(在unix中,被称为finger守护进程);
      • 而finger返回的结果是由这个进程决定的,使用或自己编些不同的进程,可以提供各种各样的finger服务;
  • 性能评测
    • 在muduo库擅长的领域(TCP长连接), 其性能不比任何开源网络库差;
    • muduo最开始并没有以高并发、高吞吐为主要目标;
      • ping pong 测试表明:

        • muduo的吞吐量比Boost.Asio高15%;
        • muduo的吞吐量比libevnet2高18%;
      • muduo与Nginx的吞吐量对比
        • 对比内置的简陋的HTTP服务器的长连接性能;
        • 直接返回内存中的数据, 比较程序的网络性能;
        • qps(每秒请求数)都能超过10万;
      • muduo与ZeroMQ的延迟对比;
        • muduo的延迟稳定的低于ZeroMQ;
  • 详解muduo库多线程模型
    • 以一个sudoku solver为例, 一个求解数独的服务器程序;
    • 从网络连接读入一个sudoku题目, 算出答案, 再发回给客户端;
    • 怎么做才能发挥多核硬件的能力;
    • 一个简单的以'\r\n'分隔的文本行协议, 使用TCP长连接, 客户端在不需要服务时主动断开连接;
  • 正确使用non-blocking IO需要考虑的问题很多, 不适宜直接调用Sockect API, 而需要一个功能完善的网络库支撑;
  • 目前高性能httpd普遍采用的是单线程Reactor方式;
    • reactors+thread pool是最灵活的IO与CPU配置;
  • 通常由网络库负责读写socket, 用户代码负责解码、计算和编码;
  • C++多线程服务器编程模式为: one loop per thread + thread pool
    • event loop 用作non-blocking IO 和定时器;
    • thread pool用来做计算, 具体可以是任务队列或生产者消费者队列;

Mudo C++网络库第六章学习笔记的更多相关文章

  1. Mudo C++网络库第十一章学习笔记

    反思C++面向对象与虚函数 C++语言学习可以看<C++ Primer>这本书; 在C++中进行面向对象编程会遇到其他语言中不存在的问题, 其本质原因是C++ class是值语义, 而非对 ...

  2. Mudo C++网络库第四章学习笔记

    C++多线程系统编程精要 学习多线程编程面临的最大思维方式的转变有两点: 当前线程可能被切换出去, 或者说被抢占(preempt)了; 多线程程序中事件的发生顺序不再有全局统一的先后关系; 当线程被切 ...

  3. Mudo C++网络库第三章学习笔记

    多线程服务器的适用场合与常用编程模型 进程间通信与线程同步; 以最简单规范的方式开发功能正确.线程安全的多线程程序; 多线程服务器是指运行在linux操作系统上的独占式网络应用程序; 不考虑分布式存储 ...

  4. Mudo C++网络库第七章学习笔记

    muduo编程示例 muduo库是设计来开发内网的网络程序, 它没有做任何安全方面的加强措施, 如果在公网上可能会受到攻击; muduo库把主动关闭连接这件事分成两步来做: 如果主动关闭连接, 会先关 ...

  5. Mudo C++网络库第五章学习笔记

    高效的多线程日志 日志(logging)有两个意思: 诊断日志(diagnostic log), 常用日志库提供日志功能; 交易日志(transaction log), 用于记录状态变更, 通过回放日 ...

  6. Spring实战第六章学习笔记————渲染Web视图

    Spring实战第六章学习笔记----渲染Web视图 理解视图解析 在之前所编写的控制器方法都没有直接产生浏览器所需的HTML.这些方法只是将一些数据传入到模型中然后再将模型传递给一个用来渲染的视图. ...

  7. 《Linux命令行与shell脚本编程大全》 第十六章 学习笔记

    第十六章:创建函数 基本的脚本函数 创建函数 1.用function关键字,后面跟函数名 function name { commands } 2.函数名后面跟空圆括号,标明正在定义一个函数 name ...

  8. 网络库Alamofire使用方法学习笔记

    Github地址 由于Alamofire是swift网络库,所以,以下的所有介绍均基于swift项目 导入Alamofire 以下为使用cocoapods导入,其余的方式请参考官网 source 'h ...

  9. apue第六章学习总结

    apue第六章学习总结 1.关于阴影文件与口令 在口令文件当中,常见的字段有(以root为例): root(用户名):x(加密口令):0(uid):0(gid):root(注释字段):/root(用户 ...

随机推荐

  1. 1.Eureka

    分布式系统中,当B的数量越来越多的时候,A只需要从注册中心获取B注册的服务,而不需要直接从B中获取服务,答案显而易见. application.yml: eureka: client: service ...

  2. Sql Server 游标例子笔记

    create PROCEDURE total_mySaleDuty as BEGIN DECLARE @a int,@error int DECLARE @b int,@errorb int DECL ...

  3. jQuery使用(五):DOM操作之插入和删除元素

    插入: insertBofore() before() insertAfter() after() appendTo() append() prependTo() prepen() 删除: remov ...

  4. JavaScript中调皮的undefined

    JavaScript中调皮的undefined 在JavaScript中undefined只是一个标识符,不是关键字,这个很不靠谱的标识符还不能像其他符号一样随意使用,一方面是需要它的原始值保持不变, ...

  5. vue使用字体图标转码问题

    使用iconfont字体之后,出现的是一个方框,而没有出现相应的图标 需要通过String.fromCharCode方法转成指定unicode编码对应的十六进制字符 <div class=&qu ...

  6. vue-cli脚手架笔记

    vue不支持IE8,因为vue使用了IE8无法模拟的 ECMAScript 5特性 使用vue-cli脚手架会让我们的工作非常方便 比如想编译一下es6的语法就使用 babel loader 和 ba ...

  7. C# UpdatePanel加载完毕回调JS

    如果 我们想UpdatePanel加载完成后做一些事情 需要使用js <script type="text/javascript"> //给ScriptManager的 ...

  8. SDL 库 无法解析的外部符号 __imp__fprintf

    VS2015 在链接器->命令行 里加入legacy_stdio_definitions.lib 另外一个常见错误关于stderr的用 extern "C" { FILE _ ...

  9. daemon_inetd函数

    #include <syslog.h> extern int daemon_proc; /* defined in error.c */ void daemon_inetd(const c ...

  10. oracle 重建索引以及导出所有的索引脚本(可以解决还原数据库文件时先还原数据,在重新用脚本创建索引)

    导出数据库备份文件 1. 备份服务器数据,采用并行方式,加快备份速度(文件日期根据具体操作日期修改) expdp jhpt/XXXX directory=databackup dumpfile=dpf ...