Linux网络之http协议

devtools/2025/2/12 8:54:49/

目录

URL

urlencode和urldecode

HTTP协议

HTTP协议的格式

如何理解/ 

HTTP请求方法

 POST和GET方法对比

HTTP常见header

HTTP响应状态码

3XX状态码

长链接和短链接 

cookies 

session 


在之前学习基于TCP的socket编程的时候,我们使用两种方法,实现了一个简单的计算器小程序。一种以结构化数据在客户端和服务器端之间进行网络传输,一种以序列化成字符串后的数据在客户端和服务器间进行网络传输。无论是上面的哪一种方案,只要能在客户端进行数据的正确发送,只要能在服务器端进行数据的正常解析接收,我们就称这是一种约定,也就称这是一种协议,这种协议是基于应用层程序员自己实现的一种协议。当然,在网络>计算机网络中,已经拥有了一些实用,现成大佬们创建好的协议------HTTP协议(超文本传输协议),这便是我们本期的内容。

URL

URL:统一资源定位符,用于定位互联网上资源的地址。URL的组成部分为:协议,域名,路径,查询参数,片段

URL图示如下。 

 URL的作用是什么呢? 

我们知道,在网络>计算机网络中,我们通过公网IP可以唯一确认一台主机,在一台主机上,我们可以通过路径确认一个文件资源,所以我们可以通过IP+路径确认一台主机上的一个文件资源。我们通常使用域名来表示一个IP,所以我们可以通过URL去访问一台主机上的一个资源。 

urlencode和urldecode

观察下图。

 为什么我们在搜索框中输入的是C++却在顶层的搜索框中出现了C%2B%2B的字符串呢?

在URL中我们有资源路径的概念,所以如果我们要检索的字符串中含有/这个字符,就必须对对应的字符进行特殊处理,即转义,转义的过程我们称为urlencode,反转义的过程我们称之为urldecode。 

转义的规则:一个字符为一个字节,一个字节就是8个bit位,而一个16进制位是4个bit位。所以我们对于一个字符,从右往左,进行转义,用一个16进制位替代4个bit位,不足补0直接处理,最终在转义的2个16进制位前加上%,这就是转移之后的字符。

下图为encode和decode的过程。 

HTTP协议

HTTP协议的格式

http请求如下。 

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, br
Connection: keep-alive

那么http请求主要由4部分组成,请求行,请求报头,空行,请求正文

  • 首行: [方法] + [url] + [版本]。
  • Header: 请求的属性, 冒号分割的键值对;每组属性之间使用\n分隔;遇到空行表示Header部分结束 。
  • Body: 空行后面的内容都是Body. Body允许为空字符串. 如果Body存在, 则在Header中会有一个 Content-Length属性来标识Body的长度 。

http响应如下。

HTTP/1.1 200 OK
Date: Mon, 23 May 2022 22:38:34 GMT
Server: Apache/2.4.1 (Unix)
Last-Modified: Wed, 18 May 2022 15:17:12 GMT
Content-Length: 1234
Content-Type: text/html; charset=UTF-8
Connection: close<!DOCTYPE html>
<html>
<head><title>Example Page</title>
</head>
<body><h1>Hello, World!</h1>
</body>
</html>

http响应也由4部分组成,状态行,响应报头,空行,响应正文

  • 首行: [版本号] + [状态码] + [状态码解释]。
  • Header: 请求的属性, 冒号分割的键值对;每组属性之间使用\n分隔;遇到空行表示Header部分结束。
  • Body: 空行后面的内容都是Body。 Body允许为空字符串,如果Body存在, 则在Header中会有一个 Content-Length属性来标识Body的长度; 如果服务器返回了一个html页面, 那么html页面内容就是在 body中。

如何理解/ 

我们自己创建一个Http的服务器端。代码如下。

#include "Sock.hpp"
#include <pthread.h>
#include <string.h>
#include <unistd.h>void *handle(void *args)
{pthread_detach(pthread_self());int fd = *(int *)args;delete (int *)args;// 定义一个缓冲区,作为输出型参数,获取client端写入的数据
#define SIZE 1024 * 10char buffer[SIZE];memset(buffer, 0, sizeof(buffer));ssize_t s = recv(fd, buffer, sizeof(buffer), 0);if (s > 0){buffer[s] = 0;// 查看读取的请求std::cout << buffer;// 对客户端进行回应std::string response = "http/1.0 200 OK\n";response += "Content-Type: text/plain\n"; // 文本类型为普通文本response += "\n";                         // 空行response += "yjd Made in China!";send(fd, response.c_str(), response.size(), 0);}close(fd);return nullptr;
}int main(int args, char *argv[])
{if (args != 2){return 1;}// 作为服务器端// 1.创建socket文件int Listen_fd = Socket::Sock();// 2.绑定IP和端口号Socket::Bind(Listen_fd, atoi(argv[1]));// 3.进行监听Socket::Listen(Listen_fd);// 4.持续的获取链接for (;;){int newfd = Socket::Accept(Listen_fd);int *fd = new int(newfd);pthread_t pid;pthread_create(&pid, nullptr, handle, (void *)fd);}return 0;
}

我们知道无论是http的请求还是响应,协议的格式,都是以一行为分割。如第一行请求行,通过第一个\n可以判断到请求行读取结束,然后读取header,读到空行意味着读取结束,最终空行之后就是请求的正文。 我们可以将http请求和http响应的每一行作为一个字符串,然后将整体的字符串拼接成一个大的字符串然后在网络中进行传输。

在浏览器中访问服务器,前端界面,后端的请求和响应如下。

在http请求中,这个/到底代表什么?代表请求根路径的资源吗?

nonono,这个/表示响应表示请求的资源的主页。 一般情况下,在服务器端,会有一个资源根目录,在这个根目录里面的html文件我们一般称之为服务器的主页,当客户端请求获取/时,其实就是返回服务器端根目录下的html主页。

index.html代码如下。

<!DOCTYPE html><html><head><meta charset="utf-8"></head><body><h3>你好 老表</h3></body>
</html>

HTTP请求方法

GET:

  • 用于请求指定资源。
  • 只用于获取数据,不应产生副作用。
  • 数据通过URL传递,长度有限。

POST

  • 用于提交数据到服务器,通常用于表单提交或文件上传。
  • 数据在请求体中发送,适合传输大量或敏感信息。

PUT

  • 用于更新或替换指定资源。
  • 如果资源不存在,可以创建新资源。

DELETE

  • 用于删除指定资源。

PATCH

  • 用于部分更新资源,仅发送需要修改的部分。

HEAD

  • 类似于GET,但只返回响应头,不返回响应体,用于获取资源的元信息。

OPTIONS

  • 用于获取服务器支持的HTTP方法或资源的通信选项。

TRACE

  • 用于回显客户端的请求,主要用于测试或诊断。

CONNECT

  • 用于建立到目标资源的隧道,通常用于SSL/TLS加密的HTTPS连接。

 一般情况下,网站只暴露三个方法:GET POST HEAD方法。

 POST和GET方法对比

我们以以下HTML代码举例,分别以GET和POST方法发送请求。

GET方法。

<!DOCTYPE html><html><head><meta charset="utf-8"></head><body><h5>hello 我是首页!</h5><h5>hello 我是表单!</h5><form action="/a/b/handler_from" method="GET">姓名: <input type="text" name="name"><br/>密码: <input type="password" name="passwd"><br/><input type="submit" value="登录"></form></body>
</html>

POST方法。 

<!DOCTYPE html><html><head><meta charset="utf-8"></head><body><h5>hello 我是首页!</h5><h5>hello 我是表单!</h5><form action="/a/b/handler_from" method="POST">姓名: <input type="text" name="name"><br/>密码: <input type="password" name="passwd"><br/><input type="submit" value="登录"></form></body>
</html>

浏览器界面如下。 

总结:

GET方法:GET方法一般用于获取请求,大部分情况下都是获取请求,但是也可以用于发送请求,通过URL以参数拼接的方式将请求发送给服务器。

POST方法:POST方法一般用于发送请求,通过将参数放于http请求的正文从而实现将参数传递给服务器端。  

除此之外GET和POST方法还有什么差别吗?

  1. 两个参数提交参数的位置不同,POST方法比较私密 ,不会回显到浏览器URL的输入框,但是GET方法会会显到输入框,增加了被盗取的风险。
  2. GET方法通过URL传参,但是URL的大小是有限制的,不同浏览器的限制不同,POST方法由正文传参,一般没有大小限制。

两种方法如何选择呢? 

如果提交的参数比较少,就使用GET方法,否则就使用POST方法。 

HTTP常见header

  1. Content-Type: 数据类型(text/html等);
  2. Content-Length: Body的长度;
  3. Host: 客户端告知服务器, 所请求的资源是在哪个主机的哪个端口上;
  4. User-Agent: 声明用户的操作系统和浏览器版本信息;
  5. referer: 当前页面是从哪个页面跳转过来的;
  6. location: 搭配3xx状态码使用, 告诉客户端接下来要去哪里访问;
  7. Cookie: 用于在客户端存储少量信息. 通常用于实现会话(session)的功能; 

HTTP响应状态码

 HTTP请求状态码大致分为5类。

  1. 1XX:information(信息性状态码),接收的请求正在处理。
  2. 2XX:Success(成功状态码),请求正常处理完毕。
  3. 3XX:Redirection(重定向状态码),需要进行附加操作以完成请求。
  4. 4XX:Client Error(客户端错误状态码),服务器无法处理请求。
  5. 5XX:Server Error(服务器错误状态码),服务器处理请求出错。

最常见的状态码, 比如 200(OK), 404(Not Found), 403(Forbidden), 302(Redirect, 重定向), 504(Bad Gateway )。

3XX状态码

3XX状态码主要分为两种,暂时重定向和永久重定向。

永久重定向:301.(网址更换,旧的网址更新成新的网址)。

临时重定向:302/307(注册之后会跳转到登录界面,点击支付跳转到支付界面这些都是临时重定向)。

无论是哪种重定向,都必须在HTTP响应的报文的header中表明location属性,告诉客户端,接下来要去哪里进行访问。

下图代码我们永久重定向到了百度官网。 

        std::string response = "http/1/1 301 Permanently moved \n";response+="Location: https://www.baidu.com/\n";response+="\n";send(fd,response.c_str(),response.size(),0);

长链接和短链接 

Http协议的底层还是使用Tcp协议进行通信的。Tcp协议通信的原理图示如下。

Tcp协议client客户端和sever服务器端进行交互主要分为五步:1.客户端建立链接2.客户端发送请求3.服务器端获取链接4.服务器端获取请求5.服务端发送响应6.服务器端关闭链接7.客户端获取响应。

打开百度新闻的主页。

百度新闻的网页,不难发现有很多的图片资源。一般情况下,Tcp协议建立并最终断开链接,这样一整个过程就加载一个资源,一个图片就是一个资源。当我们输入官网点击访问时,client会向sever发送一个http请求,同时底层通过Tcp协议建立一个链接,获取主页资源,同时sever获取到请求之后,返回了主页资源,最终关闭了链接,但是此时我们要注意,此时返回的知识主页,主页中的诸多资源还没有被加载出来,所以后续还会通过类似的建立链接,发送请求,获取请求,发送响应并关闭链接这些步骤,一步步的加载页面的所有资源,但是这样的方式效率极低,因为频繁的创建连接和关闭链接这些都是要消耗时间的,以上这种方法就是我们所谓的短链接的方式。

在http1.1版本中,支持了长链接的方式,就是第一次建立链接的时候,就一次性加载完主页面的所有资源,这样就极大的提高了效率。

简单来说,短链接就是建立一次链接加载一个资源;长链接就是建立一次链接,加载完所有资源。

cookies 

何为cookies?

谈cookies之前,我们再引入一个概念,我们称http协议是一个无状态的协议,什么是无状态的协议?就是当前的请求是和之前以及以后的请求是无关的,当前请求是完全独立的,之间的请求进行了什么操作,之后的请求进行什么操作,都与本次请求无关。

在某站主页,我们打开登录界面,输入自己的账号和密码,建立一个http请求,最终服务器端进行了匹配之后,响应返回了当前用户的主页。如果当前用户是一个vip用户,那么此时就可以点击主页某块vip视频进行观看。我们知道点击这块vip视频之后,跳转到当前vip视频的播放界面,就又是一个http请求。那么问题来了。在登录界面我们输入了用户名和密码,最终发送了http请求,加载了当前vip用户的主页。那么为什么在当前vip用户的主页点击vip视频之后,我们没有输入用户名和密码,同样的通过http请求获取到了当前用户vip视频的播放界面。如果按照我们前面所说,http请求是无状态的,那么为什么第二次http请求仍然可以加载到当前vip用户vip视频播放界面,这不是违反了http协议是无状态的协议这一规则吗?

   其实,这并没有违反这一规则,这是因为cookies的功劳。cookies本质就是浏览器中的一个文件,这个文件是由sever端在http响应报文的header中通过set_cookies这一属性设置好对应的字段之后,发送响应报文,最终在client端浏览器页面生成对应的cookies文件。

  所以当我们在登录注册界面输入了账号和密码之后,点击登录按钮,client端携带账户和密码发送了http请求,sever端接收到请求之后,将账户和密码在后端数据库进行查询,如果匹配上就会在sever端建立响应,并且在http响应报文的header中通过set_cookies属性设置好当前用户的用户名和密码字段,最终将http响应报文返回client端,供client端进行解析,并且在client端创建cookies文件,cookies文件中的内容就是在http响应报文的set_cookies中设置的字段,即用户的账号和密码。

上图为一个简单的cookies生成展示。

通过上述知识,我们就可以解释我们刚开始的现象,当一个vip用户登录账号成功并且进入主页之后,那么此时浏览器主页就生成了一个cookies文件,里面保存当前用户的账号和密码,所以之后的页面跳转(即每次http请求)都会在报文的header中携带cookies信息,直接会拿cookies中的用户信息与数据库中的进行匹配,从而省去频繁的登录(获取账号和密码)操作,提高网站的可用性。http协议仍然是无状态的,但是通过报文中header的cookies字段实现了多个http协议的“关联性”。

总的来说:1.cookies就是一个文件,里面存储用户的私密信息。

                  2.一旦网页中有cookies信息,那么以后得每次请求,在请求报文的header中都会有cookies这一属性,存放用户的私密信息。

引入了cookies的概念之后,确实是提升了网站跳转的效率,但是同时也增加了风险。

  1. 既然在客户端生成了cookies文件,那么就有可能会被恶意分子去盗取这个文件,从而获取到用户的私密信息,即账号和密码。
  2. 既然会获取到cookies文件,那么当恶意分子加载到对应的网站就有可能直接通过cookies信息直接访问到对应的网页,从而对用户的账号进行破坏。

基于此,我们又引入了session的概念。

session 

session可以理解为是cookies的进化版本。

我们不是害怕不法分子盗用用户的账号和密码吗?那我们不在cookies中保存用户的账号和密码不就行了,我们保存的是一个session_id,这个session_id是唯一的,一个用户只有一个。图示如下。

当用户点击登录按钮,client端发送http请求(传递用户的参数,即账号和密码),sever端接收到http请求之后,将用户参数与数据库中参数进行比对,如果比对成功,此时会在response报文的header中设置set_cookies属性为一个session_id,这个id在sever的磁盘中对应了一个名为id的session文件,在文件中保留了用户的账号和密码,然后sever将response传给client,client会在浏览器界面创建一个cookies文件,保存了set_cookies中设置的session_id。此后的每次请求的报文header中都会有cookies属性携带浏览器文件中的session_id。之后的每次请求的用户参数,都会通过cookies属性中的session_id去与sever磁盘中的对应的文件匹配,匹配到之后,再用里面的用户参数去数据库中进行比对,比对成功则加载对应的界面。

总的来说,session和cookies一样也是一个文件,不过这个文件的名称是一个session_id,里面保存的是用户的私密信息。

引入session之后,避免非法人员获取用户账号和密码泄露这一风险,但是通过cookies访问页面这一风险没有解决,虽然没有解决,但是仍然有其它的方法规避这一风险,大家有兴趣可以去网上查找了解一下。

以上便是本期http协议的所有内容。

本期内容到此结束^_^


http://www.ppmy.cn/devtools/157818.html

相关文章

人工智能-A*算法与卷积神经网络(CNN)结合实现路径规划

以下是一个将 A* 算法与卷积神经网络(CNN)结合实现路径规划的代码示例。主要思路是使用 A* 算法生成训练数据,然后用这些数据训练一个 CNN 模型,让 CNN 学习如何预测路径,最后使用训练好的 CNN 模型进行路径规划。 代码实现 import numpy as np import heapq import tor…

vue-vite axios bug

axios-bug http proxy error Error: write ECONNABORTED 代码写法 一般baseURL不是单写前缀就可以了吗&#xff0c;为何要写死就不会出现以上错误&#xff0c;求解。

Nginx 的 proxy_pass 使用简介

文章目录 1. 基本概念 1.1 proxy_pass 概述1.2 语法1.3 使用场景 2. 基本用法 2.1 HTTP 代理 2.1.1 基本示例2.1.2 绝对根路径 vs 相对路径 2.2 Stream 代理 3. 高级用法 3.1 正则匹配3.2 变量使用3.3 重定向3.4 精确匹配3.5 if 语句3.6 limit_except 4. 实际案例 4.1 转发到多…

计算机视觉核心任务

1. 计算机视频重要分类 计算机视觉的重要任务可以大致分为以下几类&#xff1a; 1. 图像分类&#xff08;Image Classification&#xff09; 识别图像属于哪个类别&#xff0c;例如猫、狗、汽车等。 应用场景&#xff1a;物品识别、人脸识别、医疗影像分类。代表模型&#…

如何使用 DeepSeek API 结合 VSCode 提升开发效率

引言 在当今的软件开发领域&#xff0c;API 的使用已经成为不可或缺的一部分。DeepSeek 是一个强大的 API 平台&#xff0c;提供了丰富的功能和数据&#xff0c;可以帮助开发者快速构建和优化应用程序。而 Visual Studio Code&#xff08;VSCode&#xff09;作为一款轻量级但功…

vue3+vite+ts项目中使用vue-router

vite.config.ts: import { defineConfig } from vite; import vue from vitejs/plugin-vue; import path from "path";export default defineConfig({plugins: [vue()],resolve: {alias: {"": path.resolve(__dirname, "src"),}}, });这里的__d…

算法兵法全略(译文)

目录 始计篇 谋攻篇 军形篇 兵势篇 虚实篇 军争篇 九变篇 行军篇 地形篇 九地篇 火攻篇 用间篇 始计篇 算法&#xff0c;在当今时代&#xff0c;犹如国家关键的战略武器&#xff0c;也是处理各类事务的核心枢纽。算法的世界神秘且变化万千&#xff0c;不够贤能聪慧…

xxl-job使用nginx代理https后,访问出现403异常问题解决

在nginx代理为https之前&#xff0c;xxl-job使用http访问是没有问题的&#xff0c;但是换为https后&#xff0c;访问就有以下报错&#xff1a; 很多接口都出现了403异常 DataTables warning: table idjob_list - Ajax error. For more information about this error, please s…