仿muduo库实现高并发服务器项目

1.首先什么是reactor模式?

事件驱动多路复用,统一监听所有 IO 事件,事件到达后分发交给对应回调函数处理。Reactor 不是服务器,是一套「事件调度设计模式」,是高并发服务器的核心骨架。它是一种干活的规则 / 架构思想:用一个总管(事件循环 + epoll)统一盯着所有客户端连接,哪个连接有读写 / 连接事件,就派发任务给对应函数处理。

2.我们写的这个muduo库究竟是为了做什么?

3.单reactor和多reactor的区别是什么?

4.仿muduo库的核心模型

5.bind 函数的使用

5.funcction函数底层理解

6.shared_ptr的计数器的本质

7.两个不同的智能指针的区别

8.深浅拷贝的区别

9.weak_ptr的作用

10.shared_ptr的拷贝,计数器++究竟是在拷贝谁?

11.unordered_map->second.lock()的作用

12.delete究竟是在做什么

13.正则库和正则表达式

正则表达式就是字符串的一种匹配规则;

正则库就是给我们提供这样的一套接口,让我们能实现正则匹配功能;

在后期的http协议有用;

效率没有提高,但是可以让程序员的工作变得简单;

使用实例

cpp 复制代码
#include <iostream>
#include <regex>
#include <string>

int main()
{
    //
    std::string str="GET /doubao/login?user=xiaoming&pass=12345 HTTP/1.1\r\n";
    std::smatch matches;
    std::regex e("(GET|HEAD|HTTP|POST|PUT|DELETE) ([^?]*)(?:\\?(.*))? (HTTP/1\\.[01])(?:\r\n|\n)?"); //.*表示可以匹配任意字符串,也就是不关心后面的匹配,不匹配
    //GET|HEAD|HTTP|POST|PUT|DELETE 匹配其中的任意一个
    //([^?]*)  [^?]:表示匹配非问号字符  *表示匹配一次或者多次
    //\\?(.*)  \\?表示原始的?符号,表示以?符号开始,(.*)表示匹配任意字符 空格表示以空格为结尾
    //.符号在正则表达式中表示匹配除\n\r以外的任意字符
    //\\.[01]  \\.表示原始.符号 [01]本身就是一种匹配规则,表示匹配01中的任意一个
    //(?: ...) 表示匹配某个格式字符串但是不提取,最后的?表示的是匹配前面的的表达式0次或者1次,也就是前面的表达式可有可无
    // (?:\\?(.*))? ?:\\?表示的是以问号开始的字符提取,提取的是问号之后的,即只匹配问号但是不提取问号
    bool ret= std::regex_match(str,matches,e);
    if(ret == false)
    {
        return -1;
    }
    for(auto &s:matches)
    {
        std::cout<<s<<std::endl;
    }
    return 0;
}

14.any类

std: any是一种值类型,它能够更改其类型,同时仍然具有类型安全性。也就是说,对象可以保存任意类型的值,但是它们知道当前保存的值是哪种类型。在声明此类型的对象时,不需要指定可能的类型。

设计思想

实现方法

cpp 复制代码
#include <iostream>
#include <typeinfo>
#include <assert.h>
#include <string>

class Any
{
  private:
  class holder
  {
    public:
    virtual ~holder(){}
    virtual const std::type_info & type() =0;
    virtual holder * clone() = 0;

  };

  template <class T>
  class placeHolder : public holder
  {
    public:
    placeHolder(const T &val):_val(val){}
    //获取子类对象保存的数据类型
    virtual const std::type_info &type()
    {
       return typeid(T);
    }
    //针对当前对象自身,克隆出一个新的子类对象,因为有用,且没办法通过简单的拷贝构造实现,因为不清楚是哪个子类
    virtual holder * clone()
    {
      
      return new placeHolder(_val);
    }   
    public:
    T _val;
  };

  holder * _content;

  public:
  Any():_content(NULL){}
  template<class T>
  Any(const T & val):_content(new placeHolder<T>(val)){}
  Any(const Any & other):_content(other._content?other._content->clone():NULL){}  //如果类型是一个容器的情况下
  ~Any() {delete _content;}
  Any & swap(Any & other)
  {
    std::swap(_content,other._content);
    return *this;      //返回当前对象本体
  }
  template<class T>
  T* get()
  {
    //我们想要拿到的数据类型必须和我们的容器中保存的数据类型一致
    assert(typeid(T) == _content->type());  
    return &((placeHolder<T>*)_content)->_val;
  }

  //赋值运算符重载函数
  template<class T>
  Any& operator=(const T & val) 
  { 
    //用val构造出一个Any对象容器和当前容器指针发生交换,在临时对象val释放的时候,原来的this指针也就释放了 
    Any(val).swap(*this);  //构造出一个临时的对象和当前的this交换
    return *this;  //现在这个是新的当前对象的指针
  }
  Any& operator=(const Any & other)
  {
    Any(other).swap(*this);
    return *this;
  }
};

class Test
{
  public:
  Test()
  {
    std::cout<<"构造"<<std::endl;
  }
  Test(const Test & t)
  {
    std::cout<<"拷贝"<<std::endl;
  }
  ~Test()
  {
    std::cout<<"析构"<<std::endl;
  }
  
   
};

int main()
{
  Any A;
  A=10;
  int * pa = A.get<int>();
  std::cout<<*pa<<std::endl;
  A=std::string("nihao");
  std::string *ps=A.get<std::string>();
  std::cout<<*ps<< std::endl;
  {
     Test t;
     A=t;

  }
  return 0;
} 

15.时间轮

在服务器对一些请求进行相应的时候有一些客服端连接了我们的服务器却不什么也不做,恶意站着我们的资源,因此这个时候我们就可以设计一个时间轮来上间隔多久没有反应的客户端断开连接;

实现

cpp 复制代码
#include <memory>
#include <iostream>
#include <functional>
#include <vector>
#include <cstdint>
#include <unordered_map>
#include <ctime>
#include <unistd.h>

using TaskFunc = std::function<void()>;
using ReleaseFunc = std::function<void()>;
class timerTask   //这个类中构建了时钟轮中每个结点信息
{
  private:
  uint64_t _id;
  uint32_t _timeout;
  bool _cancel;
  TaskFunc _task;
  ReleaseFunc _release;

  public:
  timerTask(uint64_t id,uint32_t delay,const TaskFunc & cb ):_id(id),_timeout(delay),_task(cb),_cancel(false){}
  ~timerTask()
  {
    if(_cancel==false)
    {
      _task();
      
    }
    _release();
  }
  void SetRelease(const ReleaseFunc & cb) 
  {
    _release = cb;
  }
  uint32_t DelayTime()
  {
     return _timeout;
  }
  void Cancel()
  {
     _cancel = true;
     printf("设置取消成功\n");
  }
};


class timerWheel
{
  private:

  int _capacity;
  int _tick;     //记录当前走到_wheel的位置
  using ptrTask = std::shared_ptr<timerTask>;
  using WeakTask= std::weak_ptr<timerTask>;
  std::vector <std::vector<ptrTask>>  _wheel;
  std::unordered_map <uint64_t,WeakTask> _timers;

  private:
  void removeTimer(uint64_t id)
  {
     auto it=_timers.find(id);
    if(it != _timers.end())  //找到了
    {
       _timers.erase(it);
    }
    return;
  }
 
  public:
  timerWheel() 
  :_capacity(60)
  ,_tick(0)
  ,_wheel(60)
  { }
  ~timerWheel() {}
 
  void AddTimerToWheel(uint64_t id,uint32_t delay,const TaskFunc & task)
  {
    ptrTask ptr(new timerTask(id,delay,task));
    ptr->SetRelease(std::bind(&timerWheel::removeTimer,this,id));    //类成员函数有隐藏的this指针参数this
    //SetRelease只有在ptr析构的时候才会被释放
    uint32_t delaytime=ptr->DelayTime();
    int pos=(delaytime+_tick)%_capacity;
    _wheel[pos].push_back(ptr);
    _timers[id] =WeakTask(ptr);   //构造
  
  }


  void wheelRefresh(uint64_t id)
  {
    
    //通过我们之前保存的timeptr信息的weak_ptr构造新的timerptr,进而成功刷新
    auto it=_timers.find(id);
    if(it == _timers.end())  //找到了
    {
       return; //没有找到,说明weak_ptr中没有保存
    }
    ptrTask ptr=it->second.lock();  //unordered_map<uin64_t,Currtimerptr>lock中存储的就是之前保存的timeptr的信息
    uint32_t delaytime=ptr->DelayTime();
    int pos=(delaytime+_tick)%_capacity;
    _wheel[pos].push_back(ptr);
  }

   void WheelRuning()
  {
    _tick=(_tick+1)%_capacity;  //+1是因为我们这个时钟轮每秒钟执行一次,每秒钟都应该可以释放一个任务
    _wheel[_tick].clear();   //直接清除掉所有在这个延迟时间执行的二维数组的全部任务

  }

  void WheelCancel(uint64_t id)
  {
    auto it=_timers.find(id);
    if(it == _timers.end())  //找到了
    {
       return; //没有找到,说明weak_ptr中没有保存
    }
    ptrTask ptr=it->second.lock();
    ptr->Cancel();
    printf("要被取消了\n");
  }
  
};

16.string 的c_str的作用

17.memchr和strchr的区别

相关推荐
脚踏实地,坚持不懈!1 小时前
Linux 6.18.7 内存分配与回收 —— 代码梳理
linux·运维·网络
2601_962300472 小时前
python在运维上可以干什么,请举几个具体的例子
运维·python·系统管理·网络监控·自动化脚本
Android系统攻城狮3 小时前
Linux Gstreamer深度解析之gst_audio_format_build_integer调用流程与实战(十二)
linux·运维·服务器·音视频·车载音视频·gstreamer进阶
天远API3 小时前
零信任架构实战:基于天远行驶OCR证识别构建自动化智能停车网关
运维·人工智能·架构·自动化
吴声子夜歌3 小时前
Shell脚本——流程控制:for循环
linux·运维·shell
可乐鸡翅yeah_3 小时前
MPEG‑TS 分片 PTS/DTS 时间戳异常排错,HLS 音画不同步定位实战
运维·测试用例·音视频·媒体·m3u8
事圆则缓3 小时前
Ubuntu 安装与配置 Samba 服务器
linux·服务器·ubuntu
zhangzeyuaaa3 小时前
Python asyncio 事件循环演进:从手动管理到现代化实践
java·服务器·python
abby4 小时前
美国多IP站群服务器Nginx配置与网络优化实操
服务器