• Webserver项目解析


    一.webserver的组成部分

    Buffer类

    用于存储需要读写的数据

    Channel类

    存储文件描述符和相应的事件,当发生事件时,调用对应的回调函数

    ChannelMap类

    Channel数组,用于保存一系列的Channel

    Dispatcher

    监听器,可以设置为epoll类型/select类型/poll类型。

    HttpRequest

    保存请求状态的类。保存请求行协议,版本号等一系列相关信息。

    HttpResponse

    设置返回响应的相关状态

    ThreadPool

    线程池,保存正在运行或者阻塞的线程

    TcpConnection

    保存建立的连接,还有一系列进行消息传递的相关参数
    在这里插入图片描述

    二.调用流程

    1.启动Httpserver服务器

    1.初始化TcpServer : tcpServerInit

    {
    listenerInit  绑定+设置监听
    eventLoopInit  创建事件循环(主线程)
    threadPoolInit  创建线程池
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5

    启动httpserver服务器

    2.调用tcpServerRun(server)方法

    2.1启动线程池

    threadPoolRun(server->threadPool)
    
    • 1

    采用for循环创建线程(workerThreadInit ),

    并且对创建的线程运行(workerThreadRun):

    workerThreadRun:
    	pthread_create创建子线程的同时绑定调用函数subThreadRunning
    		subThreadRunning:
    			eventLoopRun:启动子线程的反应堆模型
    				循环进行事件处理
    				调用dispatch进行检测,如果实现的是EpollDispatcher类,则运行的是epoll_wait方法,如果检测到了,调用fd对应的channel的相应事件的回调函数
    				eventLoopProcessTask 处理任务队列
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7

    2.2封装监听的套接字

    channelInit

    添加任务到任务队列

    eventLoopAddTask

    3.启动反应堆模型

    1. 检测有无就绪的事件, 并处理

    	调用dispatch进行检测,如果实现的是EpollDispatcher类,则运行的是epoll_wait方法,如果检测到了,调用eventAtivate,传入参数有文件描述符和对应发生的事件,eventAtivate:根据fd从channelmap取出channel调用发生事件对应的回调函数。
    如果是主反应堆,处理的是对绑定的端口的监听,如果监听到有事件发生,调用acceptConnection回调函数,和客户端建立连接,从线程池中取出一个子线程的反应堆实例, 去处理这个cfd,将cfd放到 TcpConnection中处理,然后调用eventLoopAddTask,把这个任务加到子线程的任务队列。
    如果是子反应堆,反应堆一直循环调用以下函数,dispatch用于调用多分复用,eventLoopProcessTask处理任务队列,当任务队列存在任务时候,根据任务不同类型,调用相应的函数。
    如果循环检查到任务队列有读请求,对接收到的httprequest进行解析,读取接收后调用 eventLoopAddTask(conn->evLoop, conn->channel, DELETE);往任务队列添加删除任务。
    如果循环检查到任务队列有写请求,直接开始发送数据。
    
    • 1
    • 2
    • 3
    • 4
    • 5
     dispatcher->dispatch(evLoop, 2);    // 超时时长 2s
     eventLoopProcessTask(evLoop);
    
    • 1
    • 2

    在这里插入图片描述
    add任务:
    eventLoopAdd函数:把对应的channel加入到对应线程的eventLoop的channelMap(一般是子线程),然后加入到epoll树中监听。

    remove任务
    eventLoopRemove函数:把对应的channel从对应线程的eventLoop的channelMap(一般是子线程)移除,从epoll树中移除监听。

    modify任务:
    eventLoopModify函数:把对应的channel的文件描述符修改在epoll树中的监听事件。

    2. 继续处理任务队列中的任务

    三、总体流程

    在这里插入图片描述

  • 相关阅读:
    QChart柱状图
    php练习04
    如何处理海量数据文件以及大文件数据查找
    4000字超详解指针
    【C语言】结构体+位段+枚举+联合(2)
    Django后端开发——ORM
    uniapp路由跳转的六种方式
    利用元胞自动机-人工神经网络模型预测城市未来土地利用
    tiup dm template
    MySQL_数据库的约束
  • 原文地址:https://blog.csdn.net/qq_43458555/article/details/132910808