
muduo网络库
文章平均质量分 76
muduo网络库学习笔记
东阳z
从大数据到深度学习到C++到Java
展开
-
限制并发连接数
不希望服务程序超载file descriptor 是稀缺资源, fd 耗尽是一件麻烦事若accpet(2) 返回 EMFILE 该如何应对?这意味着本进程的文件描述符已经到达上限,无法为新连接创建 socket 文件描述符。但是,既然没有 socket 文件描述符来表示这个连接,我们就无法 close(2)它。程序继续运行,回到epoll_wait处 。这时 epoll_wait 会马上返回,因为新连接还在等待处理,listening fd 还是可读的。这样程序就陷入了 busy loop,CPU .原创 2021-04-04 13:13:17 · 651 阅读 · 0 评论 -
linux gcc编译时出现 “undefined reference” 错误解决——编译muduo库错误解决
东阳的学习笔记总的来说,这个报错的意思就是说,编译器发现了一个函数的声明,但是却没有找到它的定义。我们需要将这些缺失的定义代码手动添加,来让编译器知道。把链接库作为一般的目标文件,为 GCC 指定该链接库的完整路径与文件名。解决办法如下(3选1即可)如果链接库名为 libmuduo_base.a,并且位于 /usr/lib 目录,那么下面的命令会让 GCC 编译 main.c,然后将 libmuduo_base.a 链接到 main.o:gcc main.c -o main.out /h.原创 2021-01-19 13:13:41 · 1988 阅读 · 1 评论 -
常见的5种I/O模型
学习地址:https://www.cnblogs.com/xiaoxi/p/6525396.html在《Unix网络编程》一书中提到了五种IO模型,分别是:阻塞IO、非阻塞IO、多路复用IO、信号驱动IO以及异步IO。1、阻塞IO模型最传统的一种IO模型,即在读写数据过程中会发生阻塞现象。当用户线程发出IO请求之后,内核会去查看数据是否就绪,如果没有就绪就会等待数据就绪,而用户线程就会处于阻塞状态,用户线程交出CPU。当数据就绪之后,内核会将数据拷贝到用户线程,并返回结果给用户线程,用户线程才解除b转载 2021-01-20 20:58:40 · 822 阅读 · 0 评论 -
enable_shared_from_this详解
东阳的学习笔记shared_from_this()是C++多线程编程中经常会使用的到的一种方法。问题提出:见 linux 多线程服务器编程 P23. 如果 StockFactory 的生命期比 Stock 短,那么下列语句就会 core dump// ...pStock.reset(new Stock(key), boost::bind(&StockFactory::deleteStock, this, _1));// ...为了解.原创 2021-01-29 17:36:26 · 655 阅读 · 0 评论 -
muduo库学习之线程同步01——互斥器mutex
东阳的学习笔记互斥器保护了临界区,任何时刻最多只有一个线程在此 mutex 划出的临界区内活动。单独使用 mutex 时,我们主要是为了保护共享数据。下面是使用 mutex 时的一些经验和原则:主要原则有:用RAII手法封装 mutex 的创建、销毁、加锁、解锁这四个操作。只使用非递归的 mutex (即不可重入的 mutex)不手动调用 lock() 和 unlock() 函数,一切交给栈上对象 GUARD 的构造和析构函数来完成在每次构造 GUARD 对象的时候,思考调用栈上已经持有.原创 2021-01-30 15:07:47 · 279 阅读 · 0 评论 -
muduo库学习之线程同步02——条件变量
东阳的学习笔记文章目录对于wait端:对于 signal/broadcast 端如果要等待某个条件成立,我们必须使用条件变量(condition variable)。条件变量顾名思义是一个或者多个线程等待某个布尔表达式为真,即等待别的线程唤醒它。条件变量的学名叫管程。Java Object 中内置的 wait()、notify()、notifyAll()是条件变量。条件变量只有一种正确使用的方式,几乎不可能用错。对于wait端:必须与 mutex 一起使用,该布尔表达式的读写受此 mutex.原创 2021-01-30 16:30:26 · 185 阅读 · 0 评论 -
muduo库学习之线程同步03——不要用读写锁和信号量
东阳的学习笔记文章目录不要使用读写锁不要使用信号量不要使用读写锁读写锁并不像它看上去那样那么美妙!从正确性方面来说,一种典型的易犯错误是在持有 read lock 的时候修改了共享数据。这通常发生在程序的维护阶段。程序员不小心在原来read lock保护的函数中调用了会修改状态的函数从性能方面来说,读写锁不见得比普通的 mutex_ 更高效。因为它要更新 reader 的数目。如果临界区很小,锁竞争不激烈,那么 mutex 往往会更快。在多线程编程中我们总是设法缩短临界区read.原创 2021-01-30 17:02:41 · 387 阅读 · 0 评论 -
muduo库学习之线程同步04——sleep不是同步原语
东阳的学习笔记我认为sleep()/usleep()/nanosleep()只能出现在测试代码中,比如写单元测试的时候(备注:设计时间的单元测试不那么好写,短的如一两秒可以用sleep();长的如一小时、一天,则得想其他办法,比如把算法提取出来并把时间注入进去)或者用于有意延长临界区,加速复现死锁的情况,就像“前文介绍的死锁”示范的那样sleep不具备memory barrier语义,它不能保证内存的可见性(参阅后面“C++多线程系统编程精要”的文章最开始的例子)生产代码中线程的等待可分为两.原创 2021-01-30 17:11:30 · 145 阅读 · 0 评论 -
muduo库学习之线程同步05——MutexLock、MutexLockGuard的封装
文章目录一、MutexLock、MutexLockGuard的封装MutexLockMutexLockGuard二、Condition的封装>Condition关于条件变量与互斥器的使用三、总结一、MutexLock、MutexLockGuard的封装MutexLock:封装临界区(critical section),这是一个简单的资源类,用RAII手法封装互斥器的创建与销毁。MutexLock一般是别的class的数据成员临界区在Windows上是struct CRITICAL_SEC转载 2021-01-30 17:27:15 · 339 阅读 · 0 评论 -
muduo库学习之线程同步06——Singleton单例实现
文章目录一、DCL二、pthread_once原文链接:https://blog.youkuaiyun.com/qq_41453285/article/details/104885869一、DCL研究Singleton的线程安全实现的历史会发现很多有意思的事情,人们一度认为double checked locking(缩写为DCL)是王道,兼顾了效率与正确性。后来有“神牛”指出由于乱序执行的影响,DCL是靠不住的。可以参阅:http://www.cs.umd.edu/~pugh/java/memory转载 2021-01-30 17:34:37 · 193 阅读 · 0 评论 -
muduo库学习之线程同步07——CopyOnWrite
东阳的学习笔记CopyOnWriter1 什么是COW?COW字面意思写时复制,是一种并发场景下的共享数据策略。顾名思义,它的基本思想是大家共享同一份数据,读的时候不加锁,直接读取数据;更新数据时在其拷贝副本上操作,在这个新拷贝的数据上演绎更新操作,然后再用这个新数据替换老数据。2 借 shared_ptr 实现 copy-on-write在 互斥器 那篇文章中提到了一个死锁的例子。在这里我们来看看如何使用 COW 来解决这个问题:先将数据结构改成:typedef std::vect.原创 2021-01-31 16:16:50 · 274 阅读 · 0 评论 -
muduo库学习之线程同步08——总结
东阳的学习笔记1. 内容总结前面几篇文章的内容归纳如下:线程同步的四项原则,尽量使用高层同步设施(线程池、队列、倒计时)使用普通互斥器和条件变量完成剩余的同步任务,采用 RAII惯用手法和 Scoped Locking。所谓的四项原则即:muduo库学习之线程同步01——互斥器mutex中所提到的使用原则2. 文章汇总muduo库学习之线程同步01——互斥器mutexmuduo库学习之线程同步02——条件变量muduo库学习之线程同步03——不要用读写锁和信号量muduo库.原创 2021-01-31 16:40:40 · 132 阅读 · 0 评论 -
muduo库学习之适用场合和常用编程模型01——fork函数(多进程)
东阳的学习笔记原创 2021-02-01 11:24:24 · 177 阅读 · 0 评论 -
muduo库学习之适用场合和常用编程模型02——线程
原文链接:https://blog.youkuaiyun.com/zhoucheng05_13/article/details/976121351 线程创建创建一个线程,并在主线程和子线程中打印进程id、线程id。实例代码#include "apue.h"#include<pthread.h>pthread_t tdno;//打印进程id、线程idvoid printids(const char* s){ pid_t pid; pthread_t tid; .转载 2021-02-01 11:59:40 · 168 阅读 · 0 评论 -
muduo库学习之适用场合和常用编程模型03——进程和线程
东阳的学习笔记进程和线程每个进程有自己的独立空间。“在同一个进程” 还是 “不在同一个进程”是系统功能划分的重要决策点。线程的特点是共享地址空间,从而高效地共享数据,一台机器上的多个进程能高效地共享代码段(操作系统可以映射为同样的物理内存),但不能共享数据。如果多个进程大量地共享内存,等于是把多进程程序当作多线程来写,掩耳盗铃!为什么要使用多线程作者认为是为了更好地发挥多核处理器的效能。如果只有一块CPU、一个执行单元,按状态机的思路去写程序是最高效的。...原创 2021-02-01 12:49:17 · 107 阅读 · 1 评论 -
muduo库学习之常用编程模型04——常用编程模型与进程间通信方式的选择
东阳的学习笔记文章目录1. 单线程服务器常用地编程模型2. 典型的多线程服务器的线程模型One loop per thread线程池归纳3. 进程间通信与线程间通信进程间通信原文链接:https://blog.youkuaiyun.com/yuyin86/article/details/70864241. 单线程服务器常用地编程模型常用的单线程编程模型见https://blog.youkuaiyun.com/qq_22473333/article/details/112910686在高性能的网络程序中,使用得.转载 2021-02-01 14:04:51 · 412 阅读 · 0 评论 -
muduo库学习之多线程服务器的适用场合
文章目录正名必须用单线程的场合基于进程的分布式系统设计单线程程序的优势多线程程序有性能优势吗?适用多线程程序的场景线程的分类“服务器开发”包罗万象,本文所指的“服务器开发”的含义请见《常用模型》一文,一句话形容是:跑在多核机器上的 Linux 用户态的没有用户界面的长期运行的网络应用程序。“长期运行”的意思不是指程序 7x24 不重启,而是程序不会因为无事可做而退出,它会等着下一个请求的到来。例如 wget 不是长期运行的,httpd 是长期运行的。正名与前文相同,本文的“进程”指的是 fork()转载 2021-02-01 14:33:07 · 228 阅读 · 0 评论 -
muduo库学习之C++多线程系统编程精要01——基本线程原语的选用、Linux上的线程标识、善用__thread关键字、Linux新增系统调用的启示
东阳的学习笔记学习多线程面临的最大的思维转变有两点:当前线程可能随时会被切出去,或者说被抢占了。多线程程序中事件的发生顺序不再有全局统一的先后关系多线程程序的正确性不能依赖于任何一个线程的执行速度,不能通过原地等待(sleep)来假定其他线程的事件已经发生,而必须通过适当的同步来让当前线程能够看到其他线程事件的结果。无论线程执行得快与慢(被操作系统切换出去的越多执行地越慢), 程序都应该能够正常工作。`一、基本线程原语的选用我认为用C/C++编写跨平台(只针对POSIX操作系统).转载 2021-02-01 15:44:35 · 250 阅读 · 0 评论 -
muduo库学习之C++多线程系统编程精要02——C/C++系统库的线程安全性
一、C/C++的线程库原先的C/C++标准(C89/C99/C++03)并没有涉及线程,新版的C/C++标准(C11和C++11)规定了程序在多线程下的语意,C++11还定义了一个线程库(std::thread)内存模型(memory model)对于标准而言,关键的不是定义线程库,而是规定内存模型特别是规定一个线程对某个共享变量的修改何时能被其他线程看到,这称为内存序(memory ordering)或者内存能见度 (memory visibility)从理论上讲,如果没有合适的内存模型转载 2021-02-01 15:58:33 · 218 阅读 · 0 评论 -
muduo库学习之C++多线程系统编程精要03——线程的创建与销毁
东阳的学习笔记线程的创建线程的创建比销毁要容易得多,只需要遵守下面几条原则即可:程序库不应该在未提前告知的情况下创建自己的“背景线程”尽量用相同的方式创建线程,例如muduo::Thread在进入main()函数之前不应该启动线程程序中线程的创建最好能在初始化阶段全部完成1. 程序库不应该在未提前告知的情况下创建自己的“背景线程”线程是稀缺资源,如果程序库暗地里使用了线程,可能会导致高估系统的可用资源。一旦程序中有不只一个线程就很难安全的 fork,因此程序库最好不要偷偷使用线程.原创 2021-02-01 16:47:59 · 788 阅读 · 0 评论 -
muduo库学习之C++多线程系统编程精要04——多线程与IO
东阳的学习笔记在进行多线程网络编程的时候,几个自然的问题是:如何处理IO?(一个文件只由一个进程中的一个线程来读写,这种做法显然是正确的)能否多个线程同时读写同一个 socket 文件描述符?(最好不要)我们知道用多线程同时处理多个 socket 通常可以提高效率,那么处理同一个 socket 呢?系统调用时线程安全的,但是使用不是线程安全的首先,**操作文件描述符的系统调用本身是线程安全的,**我们不用担心多个线程同时操作文件描述符会造成进程崩溃或内核崩溃但是,多个线程同时.原创 2021-02-01 20:45:17 · 386 阅读 · 0 评论 -
muduo库学习之C++多线程系统编程精要05——用RAII包装文件描述符
东阳的学习笔记POSIX分配文件描述符的方式容易串话因为 POSIX 标准要求每次打开新文件(含socket)的时候,必须使用当前最小可用的文件描述符号码。这样可能导致串话。多线程程序如何避免串话在单线程程序中,可以通过某种全局表来避免串话。但是这种方法显然不适合多线程场景!在C++中,要解决串话问题,很简单:RAII。只需要将文件描述符对象包装在 Socket 对象中。在析构函数里关闭文件描述符即可。服务器程序中不应该关闭标准输出和标准错误因为有些第三方库会在紧急情况下往 stdou.原创 2021-02-01 21:16:25 · 198 阅读 · 0 评论 -
muduo库学习之C++多线程系统编程精要06——RAII与fork
东阳的学习笔记审慎使用 fork()fork()可能会导致资源泄漏但是,假如程序会fork(),上面的假设就会被破坏了考虑下面这个例子,Foo对象构造了一次,但是析构了两次int main(){ Foo foo; //调用构造函数 fork(); //fork为两个进程 foo.doit(); //在父子进程中都使用foo //析构函数会被调用两次,父进程和子进程各一次}还可能会出现的错误:如果Foo class封装了某种资源,而.原创 2021-02-02 09:20:25 · 176 阅读 · 0 评论 -
muduo库学习之C++多线程系统编程精要07——多线程与 fork、多线程与signal
东阳的学习笔记1. 多线程与 fork多线程与 fork() 的协作性很差。这是 POSIX 系列操作系统的历史包袱。1.1 fork 一般不能在多线程程序中使用因为 Linux 的 fork() 只克隆当前线程的 thread of control,不克隆其他线程。fork() 之后,除了当前线程之外的所有线程都消失了。forkall() 是很难办到的。因为其他线程可能等在 condition variable 上面,可能阻塞在系统调用上、可能等着 metux 以进入临界区1.2 fo.原创 2021-02-02 09:20:46 · 260 阅读 · 0 评论 -
muduo库学习之详解muduo多线程模型(常见的并发网络服务器设计方案)
东阳的学习笔记12种常见方案下表是作者总结的12种常见方案,其中:互通:开发chat服务时,多个客户连接之间是否能方便地交换数据原创 2021-02-03 17:16:09 · 869 阅读 · 0 评论 -
muduo库学习之设计与实现01——什么都不做的EventLoop
东阳的学习笔记文章目录一. 基本接口1.1 构造函数1.2 loop成员函数二、工具函数2.1 getEventLoopOfCurrentThread()2.2 void EventLoop::abortNotInLoopThread一. 基本接口构造函数、析构函数、loop() 成员函数EventLoop是不可拷贝的muduo中大多数类都是不可拷贝的。class EventLoop : boost::noncopyable{public: EventLoop(); ~Eve.原创 2021-02-04 11:48:42 · 148 阅读 · 0 评论 -
muduo库学习之设计与实现02——Reactor的关键结构
东阳的学习笔记本文讲 Reactor 最核心的事件分发机制,即将 IO multiplexing 拿到的 IO 事件分发给各个文件描述符(fd)的事件处理函数。一、Channel classChannel class 的功能有一点类似 Java NIO 的 SelectableChannel 和 Selection-Key的组合:每个 Channel 对象自始自终只属于一个 EventLoop,因此每个 Channel 对象都只属于一个 IO 线程。每个 Channel 对象自始自终只.原创 2021-02-04 16:10:03 · 533 阅读 · 1 评论 -
muduo库学习之设计与实现03——TimerQueue定时器
东阳的学习笔记一、给 EventLoop 加上定时器功能。传统的 Reactor 通过控制 select() 和 poll() 的等待时间来实现定时现在的linux中有了 timerfd,我们可以用处理 IO 事件相同的方式来处理定时,代码的一致性更好。1.1 timerfd网上对于 timerfd 的文章很多,我就不总结了。见:https://www.cnblogs.com/mickole/p/3261879.html二、TimerQueue classmuduo 的定时.原创 2021-02-05 11:49:46 · 292 阅读 · 1 评论 -
muduo库学习之设计与实现04——EventLoop::runInLoop()
东阳的学习笔记一、EventLoop::runInLoop()runInLoop:在 IO 线程内执行某个用户任务回调。如果用户在当前 IO 线程调用这个函数,回调会同步进行;如果用户在其他线程调用,cb会被加入 队列中,IO 线程会被唤醒来调用这个 Functor这个功能让我们轻易地跨线程调配任务,并且不用加锁void EventLoop::runInLoop(const Functor& cb){ if (isInLoopThread()) { cb(); }.原创 2021-02-05 15:07:31 · 346 阅读 · 0 评论 -
muduo库学习之设计与实现05——实现TCP网络库
东阳的学习笔记到目前为之,Reactor 事件处理框架已初具规模,本文开始我们用它逐步实现一个非阻塞TCP网络编程库。从 poll(2)返回到再次调用 poll(2)阻塞称为一次事件循环。传统的 Reactor 实现一般会把 timers 做成循环中单独的一步。...原创 2021-02-06 12:40:21 · 178 阅读 · 1 评论 -
muduo库学习之设计与实现06——TcpServer 接受新连接
东阳的学习笔记muduo 尽量让依赖是单向的,比如,TcpServer 会用到 Acceptor,但 Acceptor 并不知道 TcpServer 的存在。本文会介绍 TcpServer 并初步实现 TcpConnection,本文只处理连接的建立,下一篇博客会处理连接的断开。TcpServer 新建连接的相关函数调用顺序见图 8-4 (有的函数名简写,省略了 poll(2) 调用)。其中 Channel::handleEvent() 的触发条件是 listening socket 可读.原创 2021-02-06 14:47:46 · 192 阅读 · 0 评论 -
muduo库学习之设计与实现07——TcpConnection 断开连接
东阳的学习笔记muduo 只有一种关闭连接的方式:被动关闭(p. 191)。即:对方先关闭连接,本地 read(2) 返回0,触发关闭逻辑。如果有必要也可给 TcpConnection 新增 forceClose() 成员函数,用于主动关闭连接,实现很简单,调用 handleClose() 即可。函数调用的逻辑如下图:一般来说数据的删除比新建要麻烦,TCP 连接也不例外。关闭连接的流程看上去有点 “绕”,原因是对象生命期管理的需要(p. 274)其中 X 表示 TcpConnect.原创 2021-02-07 15:45:01 · 548 阅读 · 0 评论 -
muduo库学习之设计和实现08——Buffer读写数据
东阳的学习笔记Buffer 是非阻塞 TCP 网络编程必不可少的东西,本节介绍用 Buffer 来处理数据输入输出。一、Buffer读取数据首先修改 s07/Callbacks.h 中 MessageCallback 的定义,现在的参数和 muduo 一样,是 Buffer* 和 Timestamp,不再是原来的(const char * buf, int len).typedef boost::function<void (const TcpConnectionPtr&, .原创 2021-02-07 20:45:27 · 452 阅读 · 2 评论 -
muduo库学习之设计与实现09——完善TcpConnection
东阳的学习笔记前面几篇所介绍的 TcpConnection 的主体功能接近完备,可以应付大部分 muduo 示例的需求了。这里再补充几个小功能.一、SIGPIPESIGPIPE 的默认行为是结束进程,在命令行程序这是合理的,但是在网络编程中, 这意味着如果对方断开连接而本地继续写入的话,这会造成服务进程意外退出。假如服务进程繁忙,没有及时处理对方断开连接的事件,就有可能出现在连接断开之后继续发送数据的情况。下面这个例子模拟了这种情况:void onConnection(const muduo:.原创 2021-02-08 13:21:02 · 244 阅读 · 1 评论 -
muduo库学习之设计与实现10——多线程TcpServer
东阳的学习笔记多线程的 TcpServer,用到了 EventLoopThreadPoll class。一、EventLoopThreadPoll用 one loop per thread 的思想实现多线程 TcpServer 的关键步骤是在新建 TcpConnection 时从 event loop poll里挑选一个 loop 给 TcpConnection 用。也就是说:多线程 TcpServer 自己的(与TcpConnection共享的) EventLoop 只用来接受新连接,而新连.原创 2021-02-08 14:24:20 · 227 阅读 · 0 评论 -
muduo库学习之设计与实现11——Connector(主动发起连接)
东阳的学习笔记主动发起连接比被动接受连接要更复杂一些:一方面是错误处理麻烦;另一方面是要考虑重试;在非阻塞网络编程中,发起连接的基本方式是调用 connect(2),当socket 变得可写时表示连接建立完毕。当然这其中要处理各类消息的错误,将其封装为 Connector class。接口如下:class Connector : boost::noncopyable{ public: typedef boost::function<void (int sockfd)> .原创 2021-02-08 15:06:07 · 194 阅读 · 0 评论 -
muduo库学习之设计与实现12——定时器的注销(TimerQueue::cancel())
东阳的学习笔记一、使用 shared_ptrTimerQueue::cancel() 的一种简单实现是用 shared_ptr 来管理 Timer 对象,再将 TimerId 定义为 weak_ptr,这样几乎不用我们做什么事情。在C++11中也足够高效,因为shared_ptr 具有移动语义,可以做到引用计数值始终不变,没有原子操作的开销。但用 shared_ptr 来管理 Timer 对象似乎有点小题大做,而且使用 shared_ptr也有一个缺点:如果用户一直持有 TimerId,会造成.原创 2021-02-08 16:36:23 · 285 阅读 · 0 评论 -
muduo库学习之设计与实现13——TcpClient
东阳的学习笔记有了 Connector、TcpClient就不难实现了,它的代码和 TcpServer 甚至有几分相似(都有 newConnection 和 removeConnection()这两个成员函数),只不过每个TcpClient只管理一个 TcpConnection。代码从略。一、要点TcpClient 具备 TcpConnection 断开之后重新连接的功能,加上 Connector 具备反复尝试连接的功能,因此客户端与服务端之间的启动先后无所谓。连接断开后初次重试的延迟应该有随.原创 2021-02-08 16:56:44 · 237 阅读 · 0 评论