大并发服务器
文章平均质量分 67
大并发服务器
ShenHang_
一个编程小菜鸡
展开
专栏收录文章
- 默认排序
- 最新发布
- 最早发布
- 最多阅读
- 最少阅读
-
muduo关键易忘点整理
Channel是 selectable IO channel,负责注册与响应IO事件,它把fd和所关注的事件绑定在一起,即一个Channel对象(通道)就是一个事件。 一个EventLoop类中有一个红黑树(EventLoop类与Poller类是组合关系),一个EventLoop类的对象所在的线程就是一个IO线程。 Acceptor类(即TcpServer类)所在的IO线程就是main reactor,负责监听连接,每个连接创建一个TcpConnection类的对象,TcpConnection类的对象所在.原创 2021-10-12 11:22:44 · 284 阅读 · 0 评论 -
std::bind
其实std::bind和boost::bind几乎完全一样。 普通函数使用std::bind #include <iostream> #include <functional> double callableFunc (double x, double y,double z) {return x+y-z;} int main() { std::function<double(double)> NewCallable1 = std::bind (callableF原创 2021-08-16 21:41:14 · 1005 阅读 · 0 评论 -
muduo_net库源码分析(十一)(EventLoopThread类、EventLoopThreadPool类实现multiple reactors)
一个程序有多个EventLoop,也就是有多个IO线程(one loop per thread)原创 2021-05-14 20:37:20 · 320 阅读 · 0 评论 -
muduo_net库源码分析(十)
创建EventLoop类的对象–>通过该对象调用EventLoop::loop–>EventLoop::loop中调用Poller::poll(多态)返回活跃的Channel对象–>调用Channel::handleEvent–>在Channel::handleEvent中,如果到来的是连接关闭事件,由于该事件是读事件,所以调用读事件回调函数(这里已经在TcpConnection类的构造函数中通过其Channel对象调用Channel::setReadCallback将TcpCo..原创 2021-05-06 16:56:16 · 306 阅读 · 1 评论 -
boost::shared_ptr分析(对TcpConnection类的对象的生存期进行管理)
智能指针很常用,由于muduo::net库中使用boost::shared_ptr对TcpConnection类的对象的生存期进行管理,因此这里先分析下boost::shared_ptr的几个新鲜的用法,进行测试。 详细的测试代码如下(测试目标写在注释里了): #include<iostream> #include<boost/enable_shared_from_this.hpp> #include<boost/shared_ptr.hpp> #include<b原创 2021-05-06 15:36:45 · 426 阅读 · 1 评论 -
muduo_net库源码分析(九)(TcpServer类、TcpConnection类)
Acceptor类的对象是TcpServer类的成员!Acceptor类与TcpServer类是组合关系。 Acceptor::handleRead–>在Acceptor::handleRead中,除了调用::accept外,还调用了应用层回调函数 newConnectionCallback_(这里通过Acceptor::setNewConnectionCallback将应用层回调函数newConnectionCallback_设置为TcpServer::newConnection) ...原创 2021-05-02 21:30:04 · 859 阅读 · 2 评论 -
muduo_net库源码分析(八)(Acceptor类)
Acceptor类原创 2021-04-28 12:36:28 · 305 阅读 · 0 评论 -
muduo_net库源码分析(七)(Socket类)
一些基础函数的使用说明可查看:linux 网络编程之TCP的C/S模型原创 2021-04-20 22:11:19 · 267 阅读 · 0 评论 -
muduo_net库源码分析(六)(EventLoopThread类创建IO线程)
EventLoopThread类 调用顺序: 主线程中:EventLoopThread::startLoop–>在EventLoopThread::startLoop调用Thread::start创建子线程,即通过Thread::start中的::pthread_create创建子线程。 子线程中:当::pthread_create创建子线程成功后子线程会自动调用线程函数EventLoopThread::threadFunc–>EventLoopThread::threadFunc的任务就是创原创 2021-04-18 19:24:12 · 297 阅读 · 0 评论 -
muduo_net库源码分析(五)(通过EventLoop::runInLoop实现跨线程调用)
pipe:等待线程关注fd[0]的可读事件,通知线程只需要往fd[1]中写入数据,fd[0]就变得可读了。 socketpair:与pipe类似,区别在于socketpair可以双向工作,pipe只能单向工作。 别忘了线程间的等待/通知还可以用条件变量实现。 一.Eventloop与Channel是聚合关系,但是有一个地方例外,这个地方就是Eventloop中等待/通知事件的Channel(即wakeupChannel_),与Eventloop是组合关系。 二.EventLoop::wakeup函数中产.原创 2021-04-17 21:28:19 · 274 阅读 · 0 评论 -
muduo_net库源码分析(四)
对应p28原创 2021-04-16 20:47:56 · 305 阅读 · 0 评论 -
muduo_net库源码分析(三)
1.定时器函数选择 1.定时函数,用于让程序等待一段时间或安排计划任务: sleep alarm usleep nanosleep clock_nanosleep getitimer / setitimer timer_create / timer_settime / timer_gettime / timer_delete timerfd_create / timerfd_gettime / timerfd_settime 2.timerfd_* 入选的原因: (1)sleep / alarm / usl原创 2021-03-31 15:50:07 · 253 阅读 · 1 评论 -
muduo_net库源码分析(二)(EventLoop类、Channel类、Poller类)
1.类图 白色的是外部类,表示对外可见,灰色的是内部类,表示对外不可见,实心的菱形表示类之间是组合关系,空心的菱形表示类之间是聚合关系( 处于聚合关系的两个类生命周期不同步,简单来说就是在类里面以指针形式定义其它类的对象;处于组合关系的两个类的生命周期同步)。 EventLoop类是对事件循环的抽象;Poller类是对IO复用的抽象,它有两个派生类PollPoller和EPollPoller,分别是对poll和epoll的封装(这里Poller是抽象类,是muduo库中唯一使用面向对象思想编程的地方,其他原创 2021-03-26 15:12:44 · 321 阅读 · 1 评论 -
muduo_net库源码分析(一)
1.TCP网络编程本质 TCP网络编程最本质是的处理三个半事件 1.连接建立:服务器accept(被动)接受连接,客户端connect(主动)发起连接。 2.连接断开:主动断开(close、shutdown),被动断开(read返回0)。 3.消息到达:文件描述符可读。 4.消息发送完毕:这算半个。对于低流量的服务,可不必关心这个事件;这里的发送完毕是指数据写入内核缓冲区,将由TCP协议栈负责数据的发送与重传,不代表对端已经接收到数据。 2.EchoServer类图 显然,这是基于对象的编程思想,在Ec原创 2021-03-25 10:25:40 · 350 阅读 · 0 评论 -
多线程与并发服务器常见模型
常见并发服务器方案 1.iterative(循环式/迭代式)服务器 iterative 只能使用短连接(每处理完一个连接,然后就关闭连接,称为短连接),不能使用长连接,如果使用长连接,意味着write需要转到read,那么整个程序就是一个单线程程序,如果此时有其它线程过来,没有办法接受连接,因为前一个线程还在read->write的循环中。也就是说如果使用长连接的话,这个程序只能够处理一个客户端,而不能处理多个客户端。要想让程序处理多个客户端,只能使用短连接。这种服务器不是真正意义上的并发服务器,原创 2021-03-24 11:04:03 · 685 阅读 · 0 评论 -
muduo_base库源码分析(十二)
LogFile类对象调用append函数时,里面会调用LogFile类的append_unlock函数,而append_unlock函数中又会通过LogFile类的嵌套类FILE的对象file_去调用嵌套类FILE的append函数,原创 2021-03-20 16:47:41 · 265 阅读 · 2 评论 -
muduo_base库源码分析(十一)
muduo库的日志默认是INFO级别原创 2021-03-18 16:32:09 · 332 阅读 · 0 评论 -
fflush()函数
fflush()函数:更新缓存区。 头文件:#include<stdio.h> 函数定义:int fflush(FILE *stream); 函数说明:调用fflush()会将缓冲区中的内容写到stream所指的文件中去.若stream为NULL,则会将所有打开的文件进行数据更新。 fflush(stdin):刷新缓冲区,将缓冲区内的数据清空并丢弃。 fflush(stdout):刷新缓冲区,将缓冲区内的数据输出到设备。 看如下代码: #inlcude<stdio.h> int ma原创 2021-03-18 11:12:21 · 35855 阅读 · 3 评论 -
C++类中使用typedef和类中使用枚举类型(muduo日志类中遇到的问题)
在学习muduo_base库中的日志类时,发现了一种新鲜的语法。 1.在类的public中typedef定义的新类型,可以在类外使用类名::新类型名的方式调用。 class Test { public: typedef int integer; ... }; 如果该语句放在public段中,则可以在类外部使用,如: Test::integer a=1;//声明一个变量 2.在类的public中声明了枚举类,那么可以通过类名::enum值直接访问枚举值,不需要通过对象。 测试代码如下(自己写的挺好的例原创 2021-03-15 21:58:17 · 595 阅读 · 0 评论 -
muduo_base库源码分析(十)
核心点:每个线程中只有一个T类型的线程特定数据,各个线程通过muduo::ThreadLocalSingleton<T>::instance()的方式,获取T类型的线程特定数据。(很巧妙!) ThreadLocalSingleton< T >类 ThreadLocalSingleton.h #ifndef MUDUO_BASE_THREADLOCALSINGLETON_H #define MUDUO_BASE_THREADLOCALSINGLETON_H #include &l.原创 2021-03-12 19:57:24 · 193 阅读 · 0 评论 -
muduo_base库源码分析(九)
__thread关键字前面已经学过了。其实本质上,线程特定数据的数据结构如下: 注意,实际数据在堆空间上。 ThreadLocal.h #ifndef MUDUO_BASE_THREADLOCAL_H #define MUDUO_BASE_THREADLOCAL_H #include <boost/noncopyable.hpp> #include <pthread.h> namespace muduo { //核心点:每创建一个ThreadLocal对象,就能创建一个线程..原创 2021-03-12 11:33:19 · 292 阅读 · 1 评论 -
muduo_base库源码分析(八)
Singleton.h #ifndef MUDUO_BASE_SINGLETON_H #define MUDUO_BASE_SINGLETON_H #include <boost/noncopyable.hpp> #include <pthread.h> #include <stdlib.h> // atexit namespace muduo { template<typename T> class Singleton : boost::nonco..原创 2021-03-11 11:19:33 · 256 阅读 · 1 评论 -
muduo_base库源码分析(七)
线程池问题本质上也是生产者-消费者问题,生产者向任务队列中添加任务,线程队列中的线程从任务队列中取出任务执行。 Task函数是要执行的任务; threads_是线程队列,是一个ptr_vector,内部存放线程指针; queue_是任务队列; start函数用来启动线程池(创建固定个数的线程); run函数用来往线程池中的任务队列添加任务; runInThread函数是线程池中的线程要执行的函数(显然每个线程要重复执行任务,所以函数中肯定有while循环); take函数:线程池中的线程函数要去任务队.原创 2021-03-10 22:11:10 · 191 阅读 · 0 评论 -
muduo_base库源码分析(六)
这两个类其实就是多生产者-多消费者模型(使用条件变量实现)。 BlockingQueue类(无界缓冲区) 基于std::deque实现。 BlockingQueue.h 很简单 因为无界,所以一个条件变量就够了。 #ifndef MUDUO_BASE_BLOCKINGQUEUE_H #define MUDUO_BASE_BLOCKINGQUEUE_H #include <muduo/base/Condition.h> #include <muduo/base/Mutex.h> .原创 2021-03-10 16:11:56 · 223 阅读 · 0 评论 -
muduo_base库源码分析(五)
MutexLock类和MutexLockGuard类 Mutex.h 很简单 #ifndef MUDUO_BASE_MUTEX_H #define MUDUO_BASE_MUTEX_H #include <muduo/base/CurrentThread.h> #include <boost/noncopyable.hpp> #include <assert.h> #include <pthread.h> namespace muduo { clas.原创 2021-03-09 22:14:01 · 281 阅读 · 0 评论 -
linux pthread_atfork函数(解决在多线程程序中fork可能造成的死锁问题)
首先来看一个问题,在linux系统中,我们都知道fork会产生一个调用进程的复制,创建出一个新的进程,那么如果父进程有多个线程会不会复制父进程的多个线程呢? 答案:子进程创建出来时只有一个线程,就是调用fork()函数的那个线程。也就是说,父进程在复制子进程的时候,只会复制当前线程的执行状态,其它线程不会复制。(https://www.cnblogs.com/wenxuanh/p/12573966.html) 在linux下,经常会调用fork来产生一个子进程,如果出现既要考虑多线程,又要考虑多进程的情况,原创 2021-03-09 12:33:20 · 706 阅读 · 0 评论 -
muduo_base库源码分析(四)
线程标识符 (1)Linux中,每个进程有一个pid,类型pid_t,由getpid()取得。Linux下的POSIX线程也有一个id,类型 pthread_t,由pthread_self()取得,该id由线程库维护,其id空间是各个进程独立的(即不同进程中的线程可能有相同的id)。Linux中的POSIX线程库实现的线程其实也是一个进程(LWP),只是该进程与主进程(启动线程的进程)共享一些资源而已,比如代码段,数据段等。 (2)有时候我们可能需要知道线程的真实pid。比如进程P1要向另外一个进程P2中.原创 2021-03-09 09:43:03 · 237 阅读 · 0 评论 -
muduo_base库源码分析(三)
Exception.h #ifndef MUDUO_BASE_EXCEPTION_H #define MUDUO_BASE_EXCEPTION_H #include <muduo/base/Types.h> #include <exception> namespace muduo { class Exception : public std::exception { public: explicit Exception(const char* what); expl.原创 2021-03-08 11:11:56 · 230 阅读 · 0 评论 -
muduo_base库源码分析(二)
解释一下上面几个原语: __sync_fetch_and_add(type *ptr, type value); 函数的返回值是 *ptr(旧值),同时 *ptr=*ptr+value __sync_val_compare_and_swap(type *ptr, type oldval, type newval); 如果 *ptr不等于oldval,那么直接函数返回 *ptr,结束; 如果 *ptr等于oldval,那么函数返回 *ptr(旧值),同时 *ptr=newval __sync_loc...原创 2021-03-07 21:39:01 · 265 阅读 · 0 评论 -
muduo_base库源码分析(一)
BOOST_STATIC_ASSERT #include <boost/static_assert.hpp> #include <cassert> class Timestamp { private: int64_t microSecondsSinceEpoch_; }; BOOST_STATIC_ASSERT(sizeof(Timestamp) == sizeof(int64_t));//编译时断言 //BOOST_STATIC_ASSERT(sizeof(int) == ..原创 2021-03-06 21:55:05 · 408 阅读 · 0 评论 -
基于对象的线程类的封装(基于boost bind/function库)
boost bind/function 例:boost bind/function库的使用 bf_test.cpp #include <iostream> #include <boost/function.hpp> #include <boost/bind.hpp> using namespace std; class Foo { public: void memberFunc(double d, int i, int j) { cout << d原创 2021-03-05 21:53:24 · 284 阅读 · 0 评论 -
面向对象的线程类的封装
Thread.h #ifndef _THREAD_H_ #define _THREAD_H_ #include <pthread.h> class Thread { public: Thread(); virtual ~Thread(); void Start(); void Join(); void SetAutoDelete(bool autoDelete); private: sta.原创 2021-03-05 17:00:47 · 314 阅读 · 0 评论 -
boost::noncopyable
可以自己简单写一个noncopyable类: class noncopyable { protected: noncopyable() = default; ~noncopyable() = default; noncopyable(const noncopyable&) = delete; noncopyable& operator=(const noncopyable&) = delete; }; class noncopyable的基本思想就是把构造函数和析构函数设置原创 2021-03-04 14:35:08 · 334 阅读 · 1 评论
分享