大并发服务器
文章平均质量分 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 · 247 阅读 · 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 · 949 阅读 · 0 评论 -
muduo_net库源码分析(十一)(EventLoopThread类、EventLoopThreadPool类实现multiple reactors)
一个程序有多个EventLoop,也就是有多个IO线程(one loop per thread)原创 2021-05-14 20:37:20 · 269 阅读 · 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 · 279 阅读 · 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 · 393 阅读 · 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 · 826 阅读 · 2 评论 -
muduo_net库源码分析(八)(Acceptor类)
Acceptor类原创 2021-04-28 12:36:28 · 273 阅读 · 0 评论 -
muduo_net库源码分析(七)(Socket类)
一些基础函数的使用说明可查看:linux 网络编程之TCP的C/S模型原创 2021-04-20 22:11:19 · 237 阅读 · 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 · 251 阅读 · 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 · 231 阅读 · 0 评论 -
muduo_net库源码分析(四)
对应p28原创 2021-04-16 20:47:56 · 264 阅读 · 0 评论 -
muduo_net库源码分析(三)
1.定时器函数选择1.定时函数,用于让程序等待一段时间或安排计划任务:sleepalarmusleepnanosleepclock_nanosleepgetitimer / setitimertimer_create / timer_settime / timer_gettime / timer_deletetimerfd_create / timerfd_gettime / timerfd_settime2.timerfd_* 入选的原因:(1)sleep / alarm / usl原创 2021-03-31 15:50:07 · 217 阅读 · 1 评论 -
muduo_net库源码分析(二)(EventLoop类、Channel类、Poller类)
1.类图白色的是外部类,表示对外可见,灰色的是内部类,表示对外不可见,实心的菱形表示类之间是组合关系,空心的菱形表示类之间是聚合关系( 处于聚合关系的两个类生命周期不同步,简单来说就是在类里面以指针形式定义其它类的对象;处于组合关系的两个类的生命周期同步)。EventLoop类是对事件循环的抽象;Poller类是对IO复用的抽象,它有两个派生类PollPoller和EPollPoller,分别是对poll和epoll的封装(这里Poller是抽象类,是muduo库中唯一使用面向对象思想编程的地方,其他原创 2021-03-26 15:12:44 · 288 阅读 · 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 · 324 阅读 · 0 评论 -
多线程与并发服务器常见模型
常见并发服务器方案1.iterative(循环式/迭代式)服务器iterative 只能使用短连接(每处理完一个连接,然后就关闭连接,称为短连接),不能使用长连接,如果使用长连接,意味着write需要转到read,那么整个程序就是一个单线程程序,如果此时有其它线程过来,没有办法接受连接,因为前一个线程还在read->write的循环中。也就是说如果使用长连接的话,这个程序只能够处理一个客户端,而不能处理多个客户端。要想让程序处理多个客户端,只能使用短连接。这种服务器不是真正意义上的并发服务器,原创 2021-03-24 11:04:03 · 625 阅读 · 0 评论 -
muduo_base库源码分析(十二)
LogFile类对象调用append函数时,里面会调用LogFile类的append_unlock函数,而append_unlock函数中又会通过LogFile类的嵌套类FILE的对象file_去调用嵌套类FILE的append函数,原创 2021-03-20 16:47:41 · 239 阅读 · 2 评论 -
muduo_base库源码分析(十一)
muduo库的日志默认是INFO级别原创 2021-03-18 16:32:09 · 301 阅读 · 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 · 35676 阅读 · 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 · 556 阅读 · 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 · 178 阅读 · 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 · 261 阅读 · 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> // atexitnamespace muduo{template<typename T>class Singleton : boost::nonco..原创 2021-03-11 11:19:33 · 233 阅读 · 1 评论 -
muduo_base库源码分析(七)
线程池问题本质上也是生产者-消费者问题,生产者向任务队列中添加任务,线程队列中的线程从任务队列中取出任务执行。Task函数是要执行的任务;threads_是线程队列,是一个ptr_vector,内部存放线程指针;queue_是任务队列;start函数用来启动线程池(创建固定个数的线程);run函数用来往线程池中的任务队列添加任务;runInThread函数是线程池中的线程要执行的函数(显然每个线程要重复执行任务,所以函数中肯定有while循环);take函数:线程池中的线程函数要去任务队.原创 2021-03-10 22:11:10 · 161 阅读 · 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 · 199 阅读 · 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 · 258 阅读 · 0 评论 -
linux pthread_atfork函数(解决在多线程程序中fork可能造成的死锁问题)
首先来看一个问题,在linux系统中,我们都知道fork会产生一个调用进程的复制,创建出一个新的进程,那么如果父进程有多个线程会不会复制父进程的多个线程呢?答案:子进程创建出来时只有一个线程,就是调用fork()函数的那个线程。也就是说,父进程在复制子进程的时候,只会复制当前线程的执行状态,其它线程不会复制。(https://www.cnblogs.com/wenxuanh/p/12573966.html)在linux下,经常会调用fork来产生一个子进程,如果出现既要考虑多线程,又要考虑多进程的情况,原创 2021-03-09 12:33:20 · 669 阅读 · 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 · 213 阅读 · 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 · 199 阅读 · 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 · 236 阅读 · 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 · 383 阅读 · 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 · 269 阅读 · 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 · 295 阅读 · 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 · 311 阅读 · 1 评论
分享