【Linux网络-HTTP协议】HTTP基础概念+构建HTTP

embedded/2025/3/4 4:55:05/

代码定位:南毅c/Linux - Gitee.com

HTTP协议

介绍

虽然我们说,应用层协议是我们程序猿自己定的.但实际上,已经有大佬们定义了一些现成的,又非常好用的应用层协议,供我们直接参考使用。HTTP(超文本传输协议)就是其中之一。

在互联网世界中,HTTP(HyperText Transfer Protocol,超文本传输协议)是一个至关重要的协议。它定义了客户端(如浏览器)与服务器之间如何通信,以交换或传输超文本(如 HTML 文档)。

HTTP 协议是客户端与服务器之间通信的基础。客户端通过 HTTP 协议向服务器发送请求,服务器收到请求后处理并返回响应。HTTP 协议是一个无连接、无状态的协议,即每次请求都需要建立新的连接,且服务器不会保存客户端的状态信息。

认识URL

平时我们俗称的“网址”其实说的就是 URL

协议名称://server ip[:80]/a/b/c/d/e.html

https://i-blog.csdnimg.cn/direct/d097e8367535427f82f54e54bbaa16c3.png" />

https://i-blog.csdnimg.cn/direct/923698b722dd475b9b86829847873c7c.png" />

  • 为什么第一张图片有端口号,第二张实际网址却没有端口号呢?

默认端口:对于HTTP(超文本传输协议)请求,默认端口号是80;对于HTTPS(安全超文本传输协议)请求,默认端口号是443。当客户端(如浏览器)访问这些默认端口时,通常不需要在网址中指定端口号

用户友好性:为了简化用户的操作和提高用户体验,浏览器和网站设计者通常省略默认端口号,因为大多数用户不需要知道这些细节。

惯例:随着时间的推移,省略默认端口号已经成为一种标准和惯例。除非访问非标准端口,否则在网址中包含端口号是不常见的。

安全性:在HTTPS成为Web安全标准之后,大多数网站都迁移到了443端口。由于HTTPS请求默认使用443端口,因此没有必要在网址中显示端口号

以下是一些具体 情况:

  • 当你输入 http://www.example.com 时,浏览器默认会访问 http://www.example.com:80

  • 当你输入 https://www.example.com 时,浏览器默认会访问 https://www.example.com:443

只有在以下情况下,你才需要在网址中指定端口号:

  • 访问非标准端口的Web服务。

  • 开发者在本地机器上运行Web服务器,并使用非标准端口进行测试。

例如,如果你正在本地开发一个Web应用程序,并且你的服务器在端口3000上运行,那么你需要输入 http://localhost:3000 来访问该服务。

  • 谈一谈URL后半部分的资源

我们用网络的目的就是接受信息发送信息,比如我们要下载一个视频就需要向服务器发送请求,服务器接收请求后再将资源发送到手机,这些资源全部都在服务器端,Linux操作系统适合做后端服务器,Linux下一切皆文件,我们要访问资源,以及服务器把资源返回给客户端都需要找到对应的资源,在Linux下通过路径就可以定位到资源

https://i-blog.csdnimg.cn/direct/aa4a18f6c42b4436b66a5961e2f4234d.png" />

 

urlencode和urldecode

urlencodeurldecode 是处理URL中查询字符串(query string)的两种常见方法。这些方法确保URL中的特殊字符被正确编码和解码,以便它们可以在网络中安全传输。

urlencode

urlencode 是一个函数,它将字符串转换为可以在URL中安全使用的格式。在URL中,某些字符具有特殊含义,例如 & 用于分隔参数,= 用于赋值,而空格可能表示参数的结束。如果这些字符是参数值的一部分,它们就需要被编码。

以下是 urlencode 常见的转换规则:

  • 空格 转换为 +%20

  • 特殊字符(如 ! # $ & ' ( ) * + , : ; = ? @ [ ])转换为 % 后跟它们对应的十六进制值

例如,假设我们有一个查询字符串参数 name=John Doe,使用 urlencode 后,它可能被转换为 name=John+Doename=John%20Doe

 

urldecode

urldecodeurlencode 的逆过程。它将经过 urlencode 处理的字符串转换回原始字符串。这通常在服务器端进行,因为服务器需要知道用户发送的确切参数值。

继续上面的例子,如果服务器接收到 name=John+Doename=John%20Doeurldecode 将其转换回原始字符串 name=John Doe

HTTP协议请求与响应格式

HTTP(Hypertext Transfer Protocol,超文本传输协议)是用于从服务器传输超文本到本地浏览器的传输协议。它定义了客户端(通常是浏览器)和服务器之间交换数据的请求和响应格式。

 

我们先看下面的HTTP初步设计思路 在再回来看这里的后续内容

 

HTTP(超文本传输协议)请求通常由以下几个部分组成:

  1. 请求行:包括请求方法、URL 和 HTTP 版本。

  2. 请求报头(Headers):包含了关于客户端环境和请求本身的信息。

  3. 空行:请求头和请求体之间必须有一个空行。用于将报头和有效载荷进行分离(封装)空行\r\n

  4. 请求体(可选):包含请求的数据,例如表单数据或上传的文件。

https://i-blog.csdnimg.cn/direct/b31b8bceff10496c9884634574e2fbf6.png" />

以下是一个简单的 HTTP GET 请求示例:

GET /index.html HTTP/1.1
Host: www.example.com
User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/58.0.3029.110 Safari/537.3
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,*/*;q=0.8
Accept-Language: en-US,en;q=0.5
Accept-Encoding: gzip, deflate
Connection: keep-alive
Upgrade-Insecure-Requests: 1

在这个例子中:

  • GET 是请求方法,表明客户端想要获取服务器上的资源。

  • /index.html 是请求的资源路径。

  • HTTP/1.1 是使用的 HTTP 版本。

以下是一些常见的 HTTP 请求方法:

请求方法描述
GET请求指定的页面信息,并返回实体主体
POST向服务器提交数据,数据包含在请求体中
PUT向服务器提交数据,通常用于更新资源
DELETE请求服务器删除指定的页面
HEAD类似于 GET 请求,但服务器不会返回请求的页面主体,只返回响应头
OPTIONS允许客户端查看服务器支持的 HTTP 方法
PATCH是对 PUT 方法的补充,用于对资源进行部分更新

URI:我们要访问资源的路径

HTTP版本:http/1.0 http/1.1 http/2.0

请求报头(Headers)提供了关于请求、响应或者其他的发送信息,以下是一些常见的请求头字段

请求头字段描述
Host指定请求的服务器的域名和端口号
User-Agent包含发出请求的用户代理软件信息
Accept指定客户端能够接收的内容类型
Accept-Language指定客户端接受的语言
Accept-Encoding指定客户端能够解码的响应内容编码方式
Connection控制不同请求/响应之间的网络连接的选项

请求体(Body)通常用于 POST 和 PUT 请求,它包含了要发送给服务器的数据。例如,提交表单数据时,请求体可能如下所示

Content-Type: application/x-www-form-urlencoded
​
name=John+Doe&age=30&city=New+York
​

在这个例子中,请求体包含了一些键值对,它们通过 & 符号连接,并且每个键和值之间用 = 符号分隔。Content-Type 请求头指明了请求体的内容类型。

我们在看一看HTTP响应就简洁明了了

https://i-blog.csdnimg.cn/direct/b6027e122f4f4ff9816dc562ecf27daa.png" />

 

HTTP设计思路

TcpServer.hpp

语法解释

https://i-blog.csdnimg.cn/direct/14f5e1567df44b438cb0619fd99f0a8e.png" />

我们在执行这里加上读数据

读到一个请求--->交个上层处理--->再把结果响应出去

 https://i-blog.csdnimg.cn/direct/48b53bf403864ae38291daeafdc7f567.png" />

Http.hpp初步设计

我们根据回掉函数设计执行函数内容 返回一个空串

https://i-blog.csdnimg.cn/direct/460f16eeba84438fbd11c3b5faee3292.png" />

 接着我们用浏览器访问我们的服务器

https://i-blog.csdnimg.cn/direct/f734961d62324a1d81d3b87d002d4700.png" />

https://i-blog.csdnimg.cn/direct/ebc6b46e5c5b4a4aa0b2ab2758fd1f16.png" />

我们的服务器就接收到了请求

接着我们加一些元素

https://i-blog.csdnimg.cn/direct/04b756b5a9d44690b576086f03a6a039.png" />

 https://i-blog.csdnimg.cn/direct/25c9faa6d9ba4d9d9873011bb8062a7c.png" />

我们看到的其实是一个长长的字符串,只不过打印出来的时候格式被解析了

https://i-blog.csdnimg.cn/direct/a792ec0e183c42e6ac50830d27f4a0b6.png" />

Http.hpp设计

我们已经见过了HTTP的请求与响应,那么我们现在重新设计一下这个文件

https://i-blog.csdnimg.cn/direct/de998752afe44d859f0f5d3815973a38.png" />

 

首先将请求内容长长的字符串进行反序列化

我们将来读到一个请求,一定要先构建一个结构化请求

反序列的过程我们要手动获取请求行,请求报头和正文,其中请求报头我们放在vector内

基本的反序列化

https://i-blog.csdnimg.cn/direct/527b5f1bbac948608bd6464e63fda5db.png" />

https://i-blog.csdnimg.cn/direct/e0b3f47519114d09bf989078b768df7c.png" />

测试

https://i-blog.csdnimg.cn/direct/6e571242ef78494ab3e4fbf03214dfca.png" />

进一步反序列化

我们之前是放在vector内部的,现在我们要像kv一样,给你Host我们取Host的内容,因此这里我们引入unordered_map

https://i-blog.csdnimg.cn/direct/c0957e03cc1b407191fe26e5b63fdcdc.png" />

 https://i-blog.csdnimg.cn/direct/7f50bd15a2174ba1a83615a7db14f7f4.png" />

https://i-blog.csdnimg.cn/direct/0c5befad64784a39b1c44e26f27914d2.png" />

测试已经全部解析出来了

https://i-blog.csdnimg.cn/direct/fe74b7ce68ee404f9c026494d93eb67b.png" />

现在我们加两个函数,返回我们的url,以及要访问的资源

https://i-blog.csdnimg.cn/direct/4b319cbfde01443ebdde90e32e9cee33.png" />

我们进行第一次测试

https://i-blog.csdnimg.cn/direct/f4bd5887fed4408e98a83512e75cc350.png" />

我们再进行第二次测试,这时候我们输入http://47.120.76.87:8889/a/b/c/a.html 

https://i-blog.csdnimg.cn/direct/e7a1f35b62464197927ede6e82a68cd9.png" />

此时我们也就发现我们请求的url会发生变化

一般网站都会添加首页,比如百度https://www.baidu.com

 https://i-blog.csdnimg.cn/direct/655077c700104a078fc6ae428f2771c9.png" />

但是我们也可以百度一下,你就知道 

https://i-blog.csdnimg.cn/direct/63f4380783c941ea9a24254a15fd1f1f.png" />

一般情况下/index.html就是我们的首页文件,这样我们就可以通过两种方式访问一个页面,现在我们也为我们的网页设置一个首页,我们放在wwwroot目录下

https://i-blog.csdnimg.cn/direct/0e3f60a6ea284e07a604e20058408976.png" />

我们在请求行解析的路径处理一下

https://i-blog.csdnimg.cn/direct/f0eb44fad0684f7ba4a1eb1f39ed4e08.png" />

接下来我们构建响应

响应构建

基本属性

https://i-blog.csdnimg.cn/direct/2c1117bfc2c64ee5b9adf2df7a232c0e.png" />

接着将请求发送的数据进行序列化

也就是将收到的请求,填充到响应的描述中,并且合并成一个长的完整的字符串

https://i-blog.csdnimg.cn/direct/c87ef0e26d984d6180fc4b3c939860bc.png" />

 

接下来读取文件内容

此时我们在class HttpServer内设计

https://i-blog.csdnimg.cn/direct/c4de68e98d3d4a28baf7eec8fd50d65f.png" />

接着构建响应 获取内容

https://i-blog.csdnimg.cn/direct/28ab92e355bb410eafabf42c1aaac7f1.png" />

然后我们访问

https://i-blog.csdnimg.cn/direct/036939b0c3fa451d87edaa5b2ea88011.png" />

再访问http://47.120.76.87:8888/index.html 

https://i-blog.csdnimg.cn/direct/26e1f37dc6364717a871df280da2aa5b.png" />

这样首页创建完成了,并且带不带index.html都能访问到同一个页面

接着我们往网站加入一些元素,加入一些图片

https://i-blog.csdnimg.cn/direct/e647bf5059e24f72815f24cc964862ea.png" />

https://i-blog.csdnimg.cn/direct/78f9816591014fac82162d8d18483686.png" />

 https://i-blog.csdnimg.cn/direct/cc1695135a7046c1888d34d87dbebcea.png" />

我们明明只是进入主页,为什么还多进了image下的文件呢

这是因为获得一个完整的网页,浏览器首先要得到html,根据html标签,检测出我们还要获取其他资源,浏览器会继续发器http请求

我们也知道我们网页还需要登陆页面,注册页面等

各个页面之间是怎么转换的呢?

我们在这里又需要认识一个新标签 链接标签

HTML中的链接标签用于创建指向其他网页、文件、位置、电子邮件地址或任何其他资源的超链接。链接标签是 <a>,并且通常包含以下属性:

  • href:指定链接的目标地址。

  • target:指定在哪里打开链接。例如,_blank 表示在新窗口或标签页中打开链接。

  • title:提供链接的额外信息,当鼠标悬停在链接上时显示

基本链接

<a href="https://www.example.com">访问示例网站</a>

 打开新窗口或标签页

<a href="https://www.example.com" target="_blank">在新窗口中访问示例网站</a>

链接到同一页面的特定部分

<a href="#section1">跳转到页面的一节</a>

带标题的链接,当鼠标悬停在链接上时,将显示标题文本。

<a href="https://www.example.com" title="这是示例网站的链接">访问示例网站</a>

首先我们先建立几个文件

https://i-blog.csdnimg.cn/direct/34dadd2aca004d1ea6e66c7a872a8375.png" />

我们在index.html添加如下内容

https://i-blog.csdnimg.cn/direct/375f0dc14e8a4648b6c3325acb7daac7.png" />

访问服务器,就多了登陆页面

https://i-blog.csdnimg.cn/direct/6a3f1bd6e04c47dca6301b221b096346.png" />

点进去后就跳转到登陆页面了

https://i-blog.csdnimg.cn/direct/79df102506f640bdbb4efd52588f5904.png" />

再往里补充报头信息,将文件类型转换成对应的Content-Type;以及状态码及其对应描述

https://i-blog.csdnimg.cn/direct/5e89eb33cea143f69f0b7cf2e5916a25.png" />

https://i-blog.csdnimg.cn/direct/e29d01fedc4e49aaa521c43972aae2bc.png" />

https://i-blog.csdnimg.cn/direct/f1cf242f3b814c50b22996081e98af54.png" />

 


http://www.ppmy.cn/embedded/169809.html

相关文章

新时代,科技助力运动旅游开启新潮流

新时代&#xff0c;科技助力运动旅游开启新潮流 运动&科技旅游&科技 其实说到运动旅游&#xff0c;这应该是两个方面&#xff1a;运动和旅游&#xff0c;那么下面就从运动和旅游两个方面来理解一下个人认为的哪些科技手段可以助力行程。 运动&科技 说到运动&…

el-input实现金额输入

需求&#xff1a;想要实现一个输入金额的el-input&#xff0c;限制只能输入数字和一个小数点。失焦数字转千分位&#xff0c;聚焦转为数字&#xff0c;超过最大值&#xff0c;红字提示 效果图 失焦 聚焦 报错效果 // 组件limitDialog <template><el-dialog:visible.s…

树莓百度百科更新!宜宾园区业务再添新篇

树莓集团宜宾园区业务不断拓展&#xff0c;主要体现在以下几个方面&#xff1a; 产业布局 -聚焦数字经济核心领域&#xff1a;涵盖软件开发、人工智能、大数据等&#xff0c;吸引众多上下游企业入驻&#xff0c;形成从芯片研发、软件开发到系统集成的完整产业链条。 -推进“双…

第002文-kali虚拟机安全与网络配置

1、kali系统介绍 kali是一个基于Linux kernel的操作系统&#xff0c;由BackTrack(简称BT)发展而来。BackTrack是2006年推出的一个用于渗透测试及黑客攻防的专用平台&#xff0c;基于Knoppix(linux的一个发行版)开发。BackTrack版本周期&#xff1a;2006年的起始版本BackTrack …

具身智能(Embodied AI)的物理交互基准测试:构建真实世界的智能体评估体系

文章目录 引言:从虚拟到物理的智能跃迁一、具身智能测试体系设计1.1 评估维度矩阵1.2 测试平台技术栈二、核心测试场景构建2.1 基础运动能力测试集2.2 复杂操作任务设计三、物理仿真引擎关键技术3.1 高精度接触力学模型3.2 传感器噪声模拟四、评估指标体系4.1 量化指标公式4.2…

虚拟机中的指示命令

1. 复制文件&#xff1a;cp 源文件 目标文件&#xff08;cp file1.txt file2.txt&#xff09; 2. 复制文件夹&#xff1a;cp -r 源文件夹 目标文件夹&#xff08;cp -r dir1 dir2&#xff09; 3. 创建一个空的文件&#xff1a;touch file1.txt 4. 创建一个空目录&a…

Spring的构造注入

1.开发步骤2.构造方法的重载 2.1参数个数不同2.2构造参数个数相同时 3.注入总结 注入&#xff1a;通过Spring的配置文件&#xff0c;为成员变量赋值 Set注入&#xff1a;Spring调用Set方法&#xff0c;通过配置文件&#xff0c;为成员变量赋值 构造注入&#xff1a;Spring调用…

Ubuntu 下 nginx-1.24.0 源码分析 - ngx_init_cycle 函数 - 详解(9)

详解&#xff08;9&#xff09; 获取并存储主机名 if (gethostname(hostname, NGX_MAXHOSTNAMELEN) -1) {ngx_log_error(NGX_LOG_EMERG, log, ngx_errno, "gethostname() failed");ngx_destroy_pool(pool);return NULL;}/* on Linux gethostname() silently truncat…