当前位置: 首页 > news >正文

手机网站与app建站公司互橙知乎

手机网站与app,建站公司互橙知乎,上海seo优化服务公司,克拉玛依燃气公司主页muduo简介 muduo是陈硕大神在Linux平台下基于C/C开发的高性能网络库#xff0c;在此基础上可以很方便的扩展#xff0c;进行二次开发编写如http服务器。muduo网络库的核心框架#xff0c;one thread per thread Reactor模式。这也是大多数Linux端高性能网络编程框架应用的主…muduo简介 muduo是陈硕大神在Linux平台下基于C/C开发的高性能网络库在此基础上可以很方便的扩展进行二次开发编写如http服务器。muduo网络库的核心框架one thread per thread Reactor模式。这也是大多数Linux端高性能网络编程框架应用的主要架构。 其本人写的《Linux多线程服务器端编程》对muduo库整个框架和设计细节进行了非常详尽的介绍和分析非常推荐大家阅读不仅仅对网络编程有帮助。 此文使用muduo编写了一个简单的echoserver服务器从用户使用的角度来进行讲解muduo的核心框架、各个组件的交互、优秀的代码设计和实现细节。从源码角度辅助理解整个muduo的实现希望对网络编程有更深的理解。 从muduo源码中提取出了其核心逻辑提供一个包含详细注释的muduo库可以配合源码阅读删除了定时器事件、大量断言判错、和客户端只保留了muduo库服务端编程的核心框架代码行数大概2000便于剖析其核心。 删减版muduo C11 阻塞、非阻塞、同步、异步的概念 简单来说阻塞、非阻塞都是对于操作I/O产生的行为I/O 无非就是读(read)和写(write)。 以一个sockfd举例无论是读还是写都有两个阶段1 等待内核中的接收/发送缓冲区就绪可读/可写2 将内核中接收缓冲区数据拷贝至用户区 或 将用户区数据拷贝至发送缓冲区。 linux下默认对sockfd读/写操作如果未就绪就默认会一直阻塞到就绪事件发生程序才会继续往下执行而如果调用了如 fcntl 系统调用对fd设置为了非阻塞即使数据未就绪也直接返回。 同步与异步 陈硕大神的原话“在处理 I/O 的时候阻塞和非阻塞都是同步 I/O。只有使用了特殊的 API 才是异步I/O。” 我的理解是 无论是阻塞I/O、非阻塞I/O、I/O多路复用都是同步I/O它们都只是一种就绪事件通知方案无论是sockfd可读还是可写了返回的都是就绪事件用户程序依旧要承担 从用户区将数据拷贝至内核发送缓冲区 或 从内核接收缓冲区将数据拷贝至用户区的时间而异步I/O通知的是事件完成用户程序不用承担数据拷贝所花费的时间拷贝操作已经由内核帮你完成一返回就可以进行下一步处理。 异步IO相对于同步IO性能更好但是编程逻辑变得更加复杂出现了问题也更难排查。 五种IO模型 阻塞IO blocking 非阻塞IO non-blocking IO多路复用IO multiplexing 信号驱动IOsignal-driven 异步IOasynchronous muduo库的框架设计 现代CPU都有许多个核心服务器这种程序也必须充分利用多核CPU的优势如何设计多线程服务器 引用 libevent 网络库作者的观点one loop per thread is usually a good model 此时问题就转化为了如何设计一个高效的EventLoop一个线程运行一个EventLoop。 EventLoop是muduo库的核心muduo库使用的是 IO multiplexing non-blocking IO LT模式。 IO多路复用一般和非阻塞IO搭配使用它们都无法单独使用不会有人对一个非阻塞的fd一直轮询读取浪费CPU资源。也不会有人在IO多路复用中使用阻塞IO读取过程中可能会阻塞当前执行流导致其余连接迟迟未响应。 muduo的LT模式 Epoll的ET模式通常是高效的代名词使用ET模式事件就绪只会通知一次即使一次未将数据读取完毕之后也不再通知减少了Epoll底层回调机制的触发次数提高了性能。 ET模式的高效是相对的为什么muduo使用LT模式我认为有以下好处 低延迟每次读取/写入只调用一次系统调用兼顾每个连接不会因为某个连接需要进行大量读写影响其余连接。数据完整性LT模式只要数据没读完就会一直上报。 Reactor 模型 Reactor模型封装了 对IO的读写、对应事件的回调 、事件操作。 The reactor design pattern is an event handling pattern for handling service requests delivered concurrently to a service handler by one or more inputs. The service handler then demultiplexes the incoming requests and dispatches them synchronously to the associated request handlers. 单个Reactor Reactor组件Event事件、Reactor反应堆、Demultiplex事件分发器、EvantHandler事件处理器 muduo库的Multiple Reactors模型 图中的每一个Reactor对应一个EventLoop一个线程运行一个EventLoop每个Loop上的客户端连接都只能由其所在的Loop进行读写。 以图上一个MianReactor2个SubReactor 为例 muduo库中MianReactor和SubReactor的交互并没有使用简单的同步队列如生产者消费者模型而是使用了高效的eventfd系统调用实现通知/唤醒机制每个Loop都持有一个eventfd句柄要通知某个Loop只要对其所拥有的eventfd写数据即可。 如果使用了同步队列在瞬时高并发的场景此同步队列很可能成为性能瓶颈同步队列简化了逻辑使代码更容易实现但维持同步的性能损耗在高并发场景可能成为性能杀手而使用eventfd 不涉及任何的 race condttion 性能杀手锁竞争、上下文切换、数据拷贝、内存申请 muduo库核心组件 Cannel 将已连接的客户端连接 connfd打包成了一个Cannel其内部封装了connfdloop_ 此Channel所在的EventLoop、event EPOLLIN/OUTrevent响应的事件和对应事件发生时的一系列回调。 muduo库中只有两种channel 用来监听新连接的 listenfd-acceptorChannel 和客户端的 connChannel acceptorChannel 注册在MainLoop的Poller上。 Poller Poller对应Reactor模型中的事件分发器向EventLoop返回就绪事件集合是具体某个IO多路复用的对象muduo库中的Poller为一个抽象类muduo提供两个具体的IO多路复用实现EpollPoller 和 PollPoller 继承Poller类重写其虚函数实现其跨平台性默认使用的是Epoll。 EventLoop ChannelList activeChannels_; std::unique_ptr poller_; int wakeupFd; - loop std::unique_ptr wakeupChannel ;EventLoop为muduo的核心一个线程对应一个EventLoopEventLoop对应上图Reactor模型中的Reactor反应堆一个EventLoop可以管理大量的Channel 和 一个Poller 。 Channel无法直接与Poller交互Channel想要修改自己所关注的事件必须通过EventLoop调用Poller的接口。 Socket和Acceptor socket 对socket 封装bind 、listen、accept 和一系列如设置端口复用的setsockopt函数。 Acceptor 主要封装了对 listenfd 相关的操作 socket bind listen 运行在baseLoop Thread和EventLoopThread Thread 对C11线程类的进一步封装 EventLoopThread one loop per thread 的体现封装了一个线程和一个EventLoop此线程运行此EventLoop EventLoopThreadPool 事件循环线程池用户调用SetThreadNum 设置SubLoop个数不包括BaseLoop如未设置线程数默认muduo库只有一个BaseLoop同时处理新连到来和已有连接的读写事件。 GetNextLoop() //通过Round Robin轮询算法获取下一个SubLoopBuffer muduo库设置了应用层的缓冲区此缓冲区是模仿Netty网络库的设计 /// A buffer class modeled after org.jboss.netty.buffer.ChannelBuffer /// code /// ------------------------------------------------------- /// | prependable bytes | readable bytes | writable bytes | /// | | (CONTENT) | | /// ------------------------------------------------------- /// | | | | /// 0 readerIndex writerIndex size /// endcode应用读数据 调用read Tcp接收缓冲区 - InputBuffer 应用写数据 调用send OutputBuffer - Tcp发送缓冲区如果一次未完全发送完毕需要将剩余数据保存到OutputBuffer中并让Poller关注此连接的EPOLLOUT事件等待下回通知再继续发送 non-blocking 网络编程中必须要有应用层的 buffer。 Non-blocking IO 的核心思想是避免阻塞在 read() 或 write() 或其他 IO 系统调用上这样可以最大限度地复用 thread-of-control让一个线程能服务于多个 socket 连接。IO 线程只能阻塞在如 select()/poll()/epoll_wait()。这样一来应用层的缓冲是必须的每个 TCP socket 都要有 input buffer 和 output buffer。 为什么必须要有 output buffer 如果程序此时要调用send()发送20k 数据可此时TcpServer发送缓冲区只能接收10k而剩下的10k数据不可能直接丢弃也不能让执行流再此阻塞等待到可写此时剩余的数据因该由网络库接管保存到TcpConnection的 OutputBuffer 中并关注EPOLLOUT事件一旦 socket 变得可写就立刻发送数据直到发送完毕。 为什么必须要有 input buffer 客户端向服务器发送20k数据服务器不会直接收到20k的完整数据可能是 5k …10k 15k… 20k… 在数据没有接收完整的数据时必须将数据缓存到InputBuffer 中等待接收到一个完整的报文再通知应用程序调用对应的业务处理进行解析。。 TcpConnection 一个连接成功的客户端对应一个TcpConnection内部封装了 Socket、Channel 、InputBuffer、OutputBuffer 和对应事件的回调。 TcpServer TcpServer 统领全局使用muduo库进行服务端编程TcpServer必不可少。 TcpServer只对外暴露出了友好、易用的接口底层复杂的网络细节已经全部被封装好了。 TcpServer主要封装了以下重要组件 Acceptor 用于接收新连接运行在baseloop上 EventLoopThreadPool创建SubLoop 还封装了一系列用户设置的回调 std::unordered_mapstd::string, TcpConnectionPtr connections_;//保存所有的连接从echoserver剖析muduo muduo库的调用链很长大量的使用到function/bind进行回调绑定下面以一个ehcoserver的运行过程从一开始的初始化操作新连接到来的处理、数据的读写和连接的断开来剖析moduo库的核心运行逻辑。 #include iostream #include functional#include string#include muduo/net/TcpServer.h #include muduo/net/EventLoop.husing namespace std::placeholders;class CharServer { public:CharServer(muduo::net::EventLoop *loop,const muduo::net::InetAddress addr,const std::string name) : server_(loop, addr, name), loop_(loop){//连接建立/连接断开都会触发此回调server_.setConnectionCallback(std::bind(CharServer::OnConnection, this, _1));//读事件发生触发此回调server_.setMessageCallback(std::bind(CharServer::OnMessage, this, _1, _2, _3));}void SetThreadNum(int num){//设置底层创建的EventLoop个数,不包括base_loopserver_.setThreadNum(num);}void Start(){server_.start();}void OnConnection(const muduo::net::TcpConnectionPtr conn){if (conn-connected()){std::cout conn-peerAddress().toIpPort() std::endl;std::cout new conn ... std::endl;}else{std::cout conn-peerAddress().toIpPort() std::endl;std::cout conn close ... std::endl;}}void OnMessage(const muduo::net::TcpConnectionPtr conn,muduo::net::Buffer *buf,muduo::Timestamp ts){std::string recv buf-retrieveAllAsString();conn-send(recv);conn-shutdown();}private:muduo::net::TcpServer server_;muduo::net::EventLoop *loop_; };int main() {muduo::net::EventLoop loop;CharServer server(loop, {127.0.0.1, 8080}, EchoServer);server.setThreadNum(3); //设置SubLoop个数server.Start(); // epoll_ctl 添加listen_fdloop.loop(); // epoll wait 阻塞等待 }以实现一个echoserver为例用户只需要绑定几个事件处理回调再调用Start就实现了一个简单的回声服务器。 初始化 创建BaseLoop对象 创建TcpServer对象 用户传入OnConnection/Onmessage - Tcpserver - TcpConnection - Channel 最终绑定到Channel上。 echoserver内封装了一个TcpServer对象TcpServer构造需要传入BaseLoop。TcpServer内封装了两个重要组件 Acceptor EventThreadPool 假设此时已经完成初始化操作用户调用setThreadNum(3) 创建了三个SubLoop此时listenfd已经被封装成了Channel并注册到了BaseLoop的Poller上每个SubLoop的Poller也已经注册了wakeupChannel每个Loop都都阻塞在epoll_wait 上。 新连接到来调用过程 数据接收的调用过程 在TcpConnection构造函数中已经设置了Channel 事件发生时的一系列回调 //给Channel设置相对应的回调channel_-SetReadCallBack(std::bind(TcpConnection::HandleRead, this, std::placeholders::_1));channel_-SetWriteCallBack(std::bind(TcpConnection::HandleWrite, this));channel_-SetCloseCallBack(std::bind(TcpConnection::HandleClose, this));channel_-SetErrorCallBack(std::bind(TcpConnection::HandleError, this));数据发送的调用过程 在CharServer::OnMassage中直接调用send() 将数据原封不动回传。 调用TcpConnection::shutdown() 并不会直接断开连接而是会等待剩余数据发送完毕了才真正调用ShutdownWrite()关闭写端并且muduo库的这种关闭连接方式必须让对端read到0也调用close() 关闭连接否则此连接会长时间保持在半关闭状态。 关闭连接的调用过程 被动关闭连接 主动关闭连接 剩下的逻辑就和被动关闭连接相同。 总结 只是简单地以一个例子讲解了muduo库服务端的核心调用链还有许多重要的细节和优秀代码设计不好使用文字表达其实是太懒了。。要真正吃透muduo库还请去多啃源码。。 通过muduo库的学习深刻理解到基于对象的程序设计和多线程下如何妙用智能指针正确管理资源的生命周期如何封装底层复杂的实现细节只对外暴露易用性强的接口 实际项目中各个组件的设计如何做到不冗余 、弱耦合
http://www.yingshimen.cn/news/5889/

相关文章:

  • 网站开发持续更新做网站卖什么东西好
  • 做公益网站有什么要求哪里买域名便宜
  • asp网站 会员注册sql可以做网站吗
  • 沈阳建设局网站南京江北新区规划图
  • 网站建设教程设网站建设唯地带
  • 中山市有什么网站推广网站扩容需要多少钱
  • 被黑网站查询什么网站有教做衣服视频的
  • 动漫网站怎么做邯郸本地网络设计
  • 怎么自己做画册网站注册安全工程师是干什么的
  • 会外语和做网站品质好物推荐怎么上
  • 网站维护工作rp网站做多大
  • 重庆建站模板平台网站空间的地址
  • 做网站的电脑六盘水遵义网站建设怎么做
  • 网站开发系统调研目的网站做301排名会掉
  • 兰州网站建设q.479185700棒网站建设预计资金投入
  • 做淘宝网站如何提取中间的提成湛江免费建站公司
  • 自己做网站可以吗西安市建设工程交易网
  • 微网站页面如何使用花生壳做网站
  • 嘉兴网站优化设计制作售卖
  • 网站导航cms著名的wordpress主题公园
  • 烟台做网站建设电话国网法治建设网站
  • 吉安网站建设jajjjcwordpress邮箱配置
  • 上海网站建设推荐案例在广州注册一个公司要多少钱
  • 如何增加网站的索引量西安建设教育网站
  • 网站建设合同违约责任自己想申请一个公司
  • 学校网站建立学校网站建设报价是多少钱
  • 江苏省住房建设厅网站首页网页设计网站世界杯
  • 青海省安建设管理部门网站惠州网络推广公司哪家好
  • 建站网站加盟网站需要每个城市做推广吗
  • 做冷冻食品的网站网站开发的公司电话