C++学习之服务器EPOLL模型、处理客户端请求、向客户端回复数、向客户端发送文件

news2025/4/16 20:59:52

目录

1.启动epoll模型

2.和客户端建立新连接

3.接受客户端Http请求数据

4.代码回顾从接受的数据中读出请求行

5.请求行解析

6.正则表达式以及匹配

7.解析请求行以及后续处理

8.对path处理说明

9.如何回复响应数据

10.对文件对应content-type如何查询

11.服务器处理流程梳理

12.和客户端断开连接处理

13.http请求处理流程回顾

14.发送状态行和响应头

15.根据文件获取content-type和发送文件

16.程序调试和访问文件测试


1.启动epoll模型

需求:
    客户端: - 浏览器
        通IP和端口访问服务器上的某个目录或者文件
        - 访问目录:
            // 192.168.1.100:8888 这个服务器提供了一个资源目录, 里边有子目录hello/world
            - 192.168.1.100:8888/hello/world/
        - 访问文件:
            //192.168.1.100 这个服务器提供了一个资源目录,里边有子目录hello, 这里边有文件 a.html
            192.168.1.100:8888/hello/a.html
    服务器: - C语言
        - 客户端的是浏览器: 使用的协议必须是http
        - 服务器提供什么功能?
            - 接受多客户端的连接
            - 应用程层使用http, 传输层协议tcp
                - 基于epoll写 / 基于libev

2.和客户端建立新连接

- 在epoll中
                - 接受新连接 -> 客户端(浏览器)
                - 通信
                    - 接收浏览器发送过来 http 请求
                        - 浏览器只给服务器发送get请求
                        - 判断是不是get请求
                    - 判断客户端访问的是不是服务器的某个资源目录
                        - 需要将这个目录中的所有的文件信息发送给浏览器
                            - 回复数据的时候, 需要使用http响应消息对回复的数据进行包装
                            - 要保证的数据是什么格式?
                                - 回复一个动态网页
                                    - 是一个列表 -><table>
                    - 判断客户端访问的是不是服务器资源目录中的某个文件
                        - 服务器需要将这个文件发送给浏览器
                            - 回复数据的时候, 需要使用http响应消息对回复的数据进行包装
                

3.接受客户端Http请求数据

- ## sscanf函数

  ```c
  // 函数原型
  // 将参数str的字符串根据参数format字符串来转换并格式化数据,转换后的结果存于对应的参数内。
  sscanf(const char *str, const char *format, ...)。
  
  具体功能如下:
  (1)根据格式从字符串中提取数据。如从字符串中取出整数、浮点数和字符串等。
  (2)取指定长度的字符串
  (3)取到指定字符为止的字符串
  (4)取仅包含指定字符集的字符串
  (5)取到指定字符集为止的字符串
  
  sscanf可以支持格式字符%[]:
  
  (1)-: 表示范围,如:%[1-9]表示只读取1-9这几个数字 %[a-z]表示只读取a-z小写字母,类似地 %[A-Z]只读取大写字母
  (2)^: 表示不取,如:%[^1]表示读取除'1'以外的所有字符 %[^/]表示除/以外的所有字符
  (3),: 范围可以用","相连接 如%[1-9,a-z]表示同时取1-9数字和a-z小写字母 
  (4)原则:从第一个在指定范围内的数字开始读取,到第一个不在范围内的数字结束%s 可以看成%[] 的一个特例 %[^ ](注意^后面有一个空格!)
  ```

4.代码回顾从接受的数据中读出请求行

  ```c
  const char *s = "http://www.baidu.com:1234";
  char protocol[32] = { 0 };
  char host[128] = { 0 };
  char port[8] = { 0 };
  sscanf(s,"%[^:]://%[^:]:%[1-9]",protocol,host,port);
  
  printf("protocol: %s\n",protocol);
  printf("host: %s\n",host);
  printf("port: %s\n",port);
  
  ///
  sscanf("123456 abcdedf", "%[^ ]", buf);
  printf("%s\n", buf);
  结果为:123456
  ///
  sscanf("123456abcdedfBCDEF", "%[1-9a-z]", buf);
  printf("%s\n", buf);
  结果为:123456abcdedf
  ///
  sscanf("123456abcdedfBCDEF", "%[^A-Z]", buf);
  printf("%s\n", buf);
  结果为:123456abcdedf
  

5.请求行解析

 ## scandir函数

  ```c
  // 头文件
  #include <dirent.h> 
  //函数定义
  /*
      函数scandir扫描dir目录下以及dir子目录下满足filter过滤模式的文件,返回的结果是compare函数经过排 
      序的,并保存在 namelist中。注意namelist是通过malloc动态分配内存的,所以在使用时要注意释放内存。
      alphasort和versionsort 是使用到的两种排序的函数。 
      当函数成功执行时返回找到匹配模式文件的个数,如果失败将返回-1。
  */
  int scandir(const char *dir,struct dirent **namelist,int (*filter)(const void *b),
                    int (* compare)(const struct dirent **, const struct dirent **));
  int alphasort(const void *a, const void *b);
  int versionsort(const void *a, const void *b);
  ```

6.正则表达式以及匹配

7.解析请求行以及后续处理

> 超文本标记语言(**H**yper **T**ext **M**arkup **L**anguage),标准通用标记语言下的一个应用。HTML 不是一种编程语言,而是一种标记语言 (markup language),是网页制作所必备的。
>
> 超文本就是指页面内可以包含图片、链接,甚至音乐、程序等非文字元素。
>
> 超文本标记语言的结构包括**“**头”部分(英语:Head)、和“主体”部分(英语:Body),其中“头”部提供关于网页的信息,“主体”部分提供网页的具体内容。

- html 特点

  - 语法非常简洁、比较松散,以相应的英语单词关键字进行组合
    - 有很多标签, 不同标签表达的意义不同, 每个标签的功能都是固定不变的
    - 不按照标准格式写网页, 也可以被解析
  - html标签不区分大小写
  - 大多数标签是成对出现的, 有开始, 有结束
    - <html></html>
    - 特殊的单标签: <img>  <hr> <br>
  - 成对的标签
  - 不成对出现的称之为短标签

- html文件命名

  - `xxx.html`
  - `xxx.htm`

8.对path处理说明

- html文件命名

  - `xxx.html`
  - `xxx.htm`

- 注释

  ```html
  <!-- 这是一个注释 -->
  ```

- 结构

  ```html
  <html>    <!-- 根标签, 代表网页的开始 -->
      <head>
          <!-- tab页的标题, 和网页的一些属性设置 -->
          <title>握手标题</title>
      </head>
      <body>
          <!-- 在网页中显示的内容 -->
      </body>
  </html>
  ```

9.如何回复响应数据

## 1.2 文字和标题标签

```html
<!--  标题标签 , h1最大的, h6最小的 -->
<h1></h1>
<h2></h2>
<h3></h3>
......
<h6></h6>

<!--  文字 , 习惯上将属性的值放到单引号, 或者双引号中 -->
<font color="blue" size="5">hello,world</font>
属性: 
    color: 文字颜色
        □ 表示方式:
            ® 英文单词: red green blue......
            ® 使用16进制的形式表示颜色: #ffffff
    
    size: 文字大小
        □  范围 1 -- 7
            ® 1最小, 7最大    
<!-- 段落 自动换行 -->
<p></p>

<!-- 换行 单标签, 末尾有没有/都可以 -->
<br/>  or <br>

<!-- 水平线 单标签, 末尾有没有/都可以 -->
<hr/>  or <hr>

<!--  文本格式  -->
加粗:
    <strong></strong> 
    <b></b> 

文本倾斜标签 
    <em></em> 
    <i></i> 

删除线标签 
    <del></del> 
    <s></s> 

下划线标签
    <ins></ins> 
    <u></u> 
```

10.对文件对应content-type如何查询

 ```http
  POST / HTTP/1.1
  Host: 192.168.1.8:6789
  Connection: keep-alive
  Content-Length: 98
  Cache-Control: max-age=0
  Upgrade-Insecure-Requests: 1
  Origin: null
  Content-Type: application/x-www-form-urlencoded
  User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/80.0.3987.106 Safari/537.36
  Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3;q=0.9
  Accept-Encoding: gzip, deflate
  Accept-Language: zh-CN,zh;q=0.9,en;q=0.8
  
  username=subwen%40qq.com&phone=1111111&email=sub%40qq.com&date=2020-01-01&sex=male&class=1&rule=on

11.服务器处理流程梳理

第 2-9 行: 响应头(消息报头)
    - Content-Type: 服务器给客户端回复的数据块的格式 == http响应第四部分的数据块格式
        - text/plain; ==> 纯文本
        - charset=iso-8859-1 ==> 数据的字符编码
            - iso-8859-1 ==> 不支持中文
            - utf8: 支持中文
    - Content-Length: 服务器给客户端回复的数据块的长度 == http响应第四部分的数据块字节数
        - 对应的value值必须是正确的数值
        - 如果不知道数据块的字节数, 可以指定-1
    
第 11-16 行: 服务器给客户端回复的响应数据

12.和客户端断开连接处理

1. http状态码

   > 状态代码有三位数字组成,第一个数字定义了响应的类别,共分五种类别:
   >
   > - 1xx:指示信息--表示请求已接收,继续处理
   > - 2xx:成功--表示请求已被成功接收、理解、接受
   > - 3xx:重定向--要完成请求必须进行更进一步的操作
   > - 4xx:客户端错误--请求有语法错误或请求无法实现
   > - 5xx:服务器端错误--服务器未能实现合法的请求

   > 常见状态码:
   >
   > - 200 OK                       客户端请求成功
   > - 400 Bad Request       客户端请求有语法错误,不能被服务器所理解
   > - 401 Unauthorized     请求未经授权,这个状态代码必须和WWW-Authenticate报头域一起使用 
   > - 403 Forbidden            服务器收到请求,但是拒绝提供服务
   > - 404 Not Found           请求资源不存在,eg:输入了错误的URL
   > - 500 Internal Server Error     服务器发生不可预期的错误
   > - 503 Server Unavailable        服务器当前不能处理客户端的请求,一段时间后可能恢复正常

13.http请求处理流程回顾

```c
/*
客户端: 浏览器
    - 通过浏览器访问服务器:
        - 访问方式: 服务器的IP地址:端口
    - 应用层协议使用: http, 数据需要在浏览器端使用该协议进行包装
    - 响应消息的处理也是浏览器完成的 => 程序猿不需要管
    - 客户端通过url访问服务器资源
        - 客户端访问的路径:
        1. http://192.168.1.100:8989/  或者  http://192.168.1.100:8989
            - 访问服务器提供的资源目录的根目录
                - 并不是服务器上的 / 目录  
                - 这个目录根据服务器端的描述应该是: /home/robin/luffy 目录
            - 请求行:
                GET / HTTP/1.1
        2. http://192.168.1.100:8989/a.txt
            - 端口后边的/代表服务器的资源根目录
                - 在服务器端路径: /home/robin/luffy 目录
            - 客户端要访问服务器上的a.txt的文件
            - a.txt 这个文件在服务器提供的资源目录中
                - 服务器上的路径: /home/robin/luffy/a.txt
            - 请求行:
                GET /a.txt HTTP/1.1
        3. http://192.168.1.100:8989/hello/a.txt
            - http://192.168.1.100:8989: 服务器地址
            - /hello/a.txt
                - /: 服务器端提供的资源根目录
                - hello: 资源根目录的子目录
                - a.txt: 在hello目录中
            - 请求行:
                GET /hello/a.txt HTTP/1.1
        4. http://192.168.1.100:8989/hello/wrold/
            - http://192.168.1.100:8989: 服务器地址
            - /hello/world/
                - /: 服务器端提供的资源根目录
                - hello: 资源根目录的子目录
                - world/: 如果world后边有/代表这是一个目录, 这个目录在hello目录中
            - 请求行:
                GET /hello/world/ HTTP/1.1
*/

14.发送状态行和响应头

// 服务器端处理的伪代码
int main()
{
    // 1. 创建监听的fd
    socket();
    // 2. 绑定
    bind();
    // 3. 设置监听
    listen();
    
    // 4. 创建epoll模型
    epoll_create();
    epoll_ctl();
    // 5. 检测
    while(1)
    {
        epoll_wait();
        // 监听的文件描述符
        accept();
        // 通信的
        // 接收数据->http请求消息
        recvAndParseHttp();
    }
    return 0;
}

15.根据文件获取content-type和发送文件

```http
HTTP/1.1 200 Ok
Server: micro_httpd
Date: Fri, 18 Jul 2014 14:34:26 GMT
Content-Type: text/plain; charset=iso-8859-1 (必选项) 
Content-Length: 32  
Location: https://www.biadu.com
Content-Language: zh-CN
Last-Modified: Fri, 18 Jul 2014 08:36:36 GMT
Connection: close

#include <stdio.h>
int main(void)
{
    printf("hello world!\n");
    return 0;
}
```

16.程序调试和访问文件测试

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/2331719.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

BUUCTF-web刷题篇(17)

26.BabyUpload 源码&#xff1a;https://github.com/imaginiso/GXY_CTF/tree/master/Web/babyupload 查看题目源码&#xff1a; 写着&#xff1a;SetHandler application/x-httpd-php 通过源码可以看出这道文件上传题目主要还是考察.htaccess配置文件的特性&#xff0c;倘若…

国网B接口协议调阅实时视频接口流程详解以及检索失败原因(电网B接口)

文章目录 一、B接口协议调阅实时视频接口介绍B.6.1 接口描述B.6.2 接口流程B.6.3 接口参数B.6.3.1 SIP头字段B.6.3.2 SIP响应码B.6.3.3 SDP参数定义B.6.3.4 RTP动态Payload定义 B.6.4 消息示例B.6.4.1 调阅实时视频请求B.6.4.2 调阅实时视频请求响应 二、B接口调阅实时视频失败…

windows11下pytorch(cpu)安装

先装anaconda 见最下方 Pytorch 官网&#xff1a;PyTorch 找到下图&#xff08;不要求版本一样&#xff09;&#xff08;我的电脑是集显&#xff08;有navdia的装gpu&#xff09;&#xff0c;装cpu&#xff09; 查看已有环境列表 创建环境 conda create –n 虚拟环境名字(…

NVR接入录像回放平台用EasyCVR打造地下车库安防:大型商居安全优选方案

一、背景分析 随着居民生活品质的提升&#xff0c;大型商业建筑和住宅小区纷纷配套建设地下停车库。但是地下车库盗窃、失火、恶意毁坏车辆、外部人员随意进出等事件频发&#xff0c;部署视频监控系统成为保障地下车库的安全关键举措。 目前&#xff0c;很多商业和住宅都会在…

乾元通渠道商中标川藏铁路西藏救援队应急救援装备项目

乾元通渠道商中标川藏铁路西藏救援队应急救援装备项目&#xff0c;项目内通信指挥车基于最新一代应急指挥车解决方案打造&#xff0c;配合乾元通自研的车载多链路聚合路由及系统&#xff0c;主要用途为保障应急通讯&#xff0c;满足任务执行时指挥协调、通信联络及数据传输的要…

左右开弓策略思路

一、策略概述 本策略是一种基于多种技术指标的复杂交易策略&#xff0c;包括自定义指标计算、过滤平滑处理以及交易信号生成。 该策略通过不同的交易平台代码段实现&#xff0c;旨在通过分析历史价格数据来预测未来价格走势&#xff0c;并据此生成交易信号。 二、主要技术指标…

【MYSQL从入门到精通】数据类型及建表

一些基础操作语句 1.使用客户端工具连接数据库服务器&#xff1a;mysql -uroot -p 2.查看所有数据库&#xff1a;show databases; 3.创建属于自己的数据库&#xff1a; create database 数据库名;create database if not exists 数据库名; 强烈建议大家在建立数据库时指定编…

【动态规划】 深入动态规划—两个数组的dp问题

文章目录 前言例题一、最长公共子序列二、不相交的线三、不同的子序列四、通配符匹配五、交错字符串六、两个字符串的最小ASCII删除和七、最长重复子数组 结语 前言 问题本质 它主要围绕着给定的两个数组展开&#xff0c;旨在通过对这两个数组元素间关系的分析&#xff0c;找出…

结合大语言模型整理叙述并生成思维导图的思路

楔子 我比较喜欢长篇大论。这在代理律师界被视为一种禁忌。 我高中一年级的时候因为入学成绩好&#xff08;所在县榜眼名次&#xff09;&#xff0c;直接被所在班的班主任任命为班长。我其实不喜欢这个岗位。因为老师一来就要提前注意到&#xff0c;要及时喊“起立”、英语课…

【力扣hot100题】(073)数组中的第K个最大元素

花了两天时间搞明白答案的快速排序和堆排序。 两种都写了一遍&#xff0c;感觉堆排序更简单很多。 两种都记录一下&#xff0c;包括具体方法和易错点。 快速排序 class Solution { public:vector<int> nums;int quicksort(int left,int right,int k){if(leftright) r…

mapbox基础,加载F4Map二维地图

👨‍⚕️ 主页: gis分享者 👨‍⚕️ 感谢各位大佬 点赞👍 收藏⭐ 留言📝 加关注✅! 👨‍⚕️ 收录于专栏:mapbox 从入门到精通 文章目录 一、🍀前言1.1 ☘️mapboxgl.Map 地图对象1.2 ☘️mapboxgl.Map style属性二、🍀F4Map 简介2.1 ☘️技术特点2.2 ☘️核…

Android:Android Studio右侧Gradle没有assembleRelease等选项

旧版as是“Do not build Gradle task list during Gradle sync” 操作这个选项。 参考这篇文章&#xff1a;Android Studio Gradle中没有Task任务&#xff0c;没有Assemble任务&#xff0c;不能方便导出aar包_gradle 没有task-CSDN博客 在as2024版本中&#xff0c;打开Setting…

DRAM CRC:让DDR5内存数据更靠谱

DRAM(动态随机存取存储器)是电脑内存的核心部件,负责存储和传输数据。如果数据在传输中出错,后果可能很严重,比如程序崩溃或者数据损坏。为了解决这个问题,DDR5内存引入了一个新功能,叫DRAM CRC(循环冗余校验)。简单来说,它是用来检查读写数据有没有问题的工具。 下面…

心率测量-arduino+matlab

参考&#xff1a;【教程】教你玩转Stduino之手指心跳检测模块 - 知乎 (zhihu.com) 1 原理 心跳检测模块&#xff0c;由一个红外线发射LED和红外接收器构成。手指心跳监测模块能够测量脉搏&#xff0c;是这样工作的&#xff1a;当手指放在发射器与接收器之间&#xff0c;红外发射…

H3C的MSTP+VRRP高可靠性组网技术(MSTP单域)

以下内容纯为博主分享自己的想法和理解&#xff0c;如有错误轻喷 MSTP多生成树协议可以基于不同实例实现不同VLAN之间的负载分担 VRRP虚拟路由器冗余协议可以提高网关的可靠性防止单点故障的可能 在以前这两种协议通常一起搭配组网&#xff0c;来提高网络的可靠性和稳定性&a…

字符串替换 (模拟)神奇数 (数学)DNA序列 (固定长度的滑动窗口)

⭐️个人主页&#xff1a;小羊 ⭐️所属专栏&#xff1a;每日两三题 很荣幸您能阅读我的文章&#xff0c;诚请评论指点&#xff0c;欢迎欢迎 ~ 目录 字符串替换 &#xff08;模拟&#xff09;神奇数 &#xff08;数学&#xff09;DNA序列 &#xff08;固定长度的滑动窗口&am…

Linux驱动-块设备驱动

Linux驱动-块设备驱动 一&#xff0c;块设备驱动简介二&#xff0c;无请求队列情况&#xff08;EMMC和SD卡等&#xff09;三&#xff0c;请求队列情况&#xff08;磁盘等带有I/O调度的设备&#xff09;四&#xff0c;两者在驱动上区别 一&#xff0c;块设备驱动简介 块设备驱动…

【算法学习】链表篇:链表的常用技巧和操作总结

算法学习&#xff1a; https://blog.csdn.net/2301_80220607/category_12922080.html?spm1001.2014.3001.5482 前言&#xff1a; 在各种数据结构中&#xff0c;链表是最常用的几个之一&#xff0c;熟练使用链表和链表相关的算法&#xff0c;可以让我们在处理很多问题上都更加…

2台8卡L20服务器集群推理方案

1、整体流程梳理 #mermaid-svg-0aNtsWUnOH7ewXpN {font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;fill:#333;}#mermaid-svg-0aNtsWUnOH7ewXpN .error-icon{fill:#552222;}#mermaid-svg-0aNtsWUnOH7ewXpN .error-text{fill:#552222;stroke:#55…

HarmonyOS:使用geoLocationManager (位置服务)获取位置信息

一、简介 位置服务提供GNSS定位、网络定位&#xff08;蜂窝基站、WLAN、蓝牙定位技术&#xff09;、地理编码、逆地理编码、国家码和地理围栏等基本功能。 使用位置服务时请打开设备“位置”开关。如果“位置”开关关闭并且代码未设置捕获异常&#xff0c;可能导致应用异常。 …