• TinyWebServer学习笔记-Config


    为了弄清楚具体的业务逻辑,我们直接从主函数开始看源代码:

    1. #include "config.h"
    2. int main(int argc, char *argv[])
    3. {
    4. //需要修改的数据库信息,登录名,密码,库名
    5. string user = "root";
    6. string passwd = "root";
    7. string databasename = "qgydb";
    8. //命令行解析
    9. Config config;
    10. config.parse_arg(argc, argv);
    11. WebServer server;
    12. //初始化
    13. server.init(config.PORT, user, passwd, databasename, config.LOGWrite,
    14. config.OPT_LINGER, config.TRIGMode, config.sql_num, config.thread_num,
    15. config.close_log, config.actor_model);
    16. //日志
    17. server.log_write();
    18. //数据库
    19. server.sql_pool();
    20. //线程池
    21. server.thread_pool();
    22. //触发模式
    23. server.trig_mode();
    24. //监听
    25. server.eventListen();
    26. //运行
    27. server.eventLoop();
    28. return 0;
    29. }

    可以看到第一个需要弄明白的就是Config文件,那么现在我们进入头文件:

    1. class Config
    2. {
    3. public:
    4. Config();
    5. ~Config(){};
    6. void parse_arg(int argc, char*argv[]);
    7. //端口号
    8. int PORT;
    9. //日志写入方式
    10. int LOGWrite;
    11. //触发组合模式
    12. int TRIGMode;
    13. //listenfd触发模式
    14. int LISTENTrigmode;
    15. //connfd触发模式
    16. int CONNTrigmode;
    17. //优雅关闭链接
    18. int OPT_LINGER;
    19. //数据库连接池数量
    20. int sql_num;
    21. //线程池内的线程数量
    22. int thread_num;
    23. //是否关闭日志
    24. int close_log;
    25. //并发模型选择
    26. int actor_model;
    27. };

    可以看到都是一些标志,用来配置服务器的熟悉。

    首先我们来熟悉两个模式:ET和LT,以socket的读事件为例,水平模式只要socket上有未读完的数据就会一直产生EPOLLIN事件;对于边缘模式,socket上每新来一次数据就会触发一次,如果上一次触发后,没有将socket上的数据读完,也不会再次触发,除非再来新的数据。对于socket写事件,如果socket的TCP窗口一致不饱和,会一直出发EPOLLOUT事件,对于边缘模式,只会触发一次,除非TCP窗口从不饱和变成饱和再一次变成不饱和才会触发。(饱和=写缓冲区已经满了)

    在LT模式下,读事件触发后,可以按需收取想要的字节数,不用吧本次接收到的数据一次性拿走。而ET模式下则必须将数据读取干净,因为你不一定有下次机会收取数据,即使收取也是上次没读完的,造成客户端响应延迟。在LT模式下,不需要写事件一定要移除,避免不必要的触发,浪费CPU资源,ET模式下,写事件触发后,如果还要下一次的写事件触发来驱动任务,需要继续注册检测可写事件。

    I/OLTET
    socket上无数据->有数据socket上无数据->有数据
    socket上有数据socket上新来一次数据
    socket可写socket不可写->可写
    socket不可写->可写

    现在大部分属性可以直到是什么意思了,再来看OPT_LINGER(优雅连接)。当我们服务器关闭时采用优雅连接时采取下面的步骤:

    1.停止接受新的连接请求,继续处理已建立连接的请求;

    2.等待未完成的数据传输;

    3.文件传输完成,服务器关闭连接,释放相关资源。

    而非优雅连接则是不保证数据的完整性和安全性,直接将连接断开。

    还有就是并发模型,常用的并发模型有两个,Proactor和Reactor:

    Reactor要求主线程只负责监听文件描述符是否有事件发生,有则通知工作单元将socket可读可写事件放入请求队列,交由工作现场处理
    Proactor将所有的I/O操作都交给主线程和内核来完成,工作线程只负责处理逻辑,例如主线程完成read后,选择一个工作线程来处理具体请求

    现在我们聚焦于Config提供的 void Config::parse_arg(int argc, char*argv[])这个函数

    1. void Config::parse_arg(int argc, char*argv[]){
    2. int opt;
    3. const char *str = "p:l:m:o:s:t:c:a:";
    4. while ((opt = getopt(argc, argv, str)) != -1)
    5. {
    6. switch (opt)
    7. {
    8. case 'p':
    9. {
    10. PORT = atoi(optarg);
    11. break;
    12. }
    13. case 'l':
    14. {
    15. LOGWrite = atoi(optarg);
    16. break;
    17. }
    18. case 'm':
    19. {
    20. TRIGMode = atoi(optarg);
    21. break;
    22. }
    23. case 'o':
    24. {
    25. OPT_LINGER = atoi(optarg);
    26. break;
    27. }
    28. case 's':
    29. {
    30. sql_num = atoi(optarg);
    31. break;
    32. }
    33. case 't':
    34. {
    35. thread_num = atoi(optarg);
    36. break;
    37. }
    38. case 'c':
    39. {
    40. close_log = atoi(optarg);
    41. break;
    42. }
    43. case 'a':
    44. {
    45. actor_model = atoi(optarg);
    46. break;
    47. }
    48. default:
    49. break;
    50. }
    51. }
    52. }

    里面使用了下面的函数和optarg:

    int getopt(int argc, char * const argv[], const char *optstring);  
    

    这里讲一下,getopt函数是用于解析命令行参数的C库函数,允许程序从命令行获取选项和参数,根据用户提供的选项规则进行解析:

    argc:命令行参数的数量;

    argv:命令行参数的数组;

    str:一个包含选项字符的字符串,表示程序所支持的命令行选项,每个选项后面加上一个冒号代表该选项需要一个参数。

    比如在本项目中,默认指定端口号是9006,也可以在启动是手动设置:

    ./server -p 9999

    在程序运行时,会进入下面的代码块中:

    1. case 'p':
    2. {
    3. PORT = atoi(optarg);
    4. break;
    5. }

    这样我们输入的'-p'和上面的case 'p'对应起来,optarg的值就是输入的9999,然后将PORT的值赋值为9999。

  • 相关阅读:
    moea中return, risk的计算
    JS Regex
    H.迷宫,(算法选修)
    如何开发一个 Safari 插件
    iis站点https绑定
    Vue3 父组件调用子组件方法($refs 在setup()、<script setup> 中使用)
    毕业答辩PPT怎么做?制作PPT必备的模板网站和AI工具来了!
    Git 标签(Tag)实战:打标签和删除标签的步骤指南
    SPA项目开发之CRUD+表单验证
    Android 12 S 系统开机流程分析(一)
  • 原文地址:https://blog.csdn.net/pan_1214_/article/details/133516831