一、HTTP协议
1.1 简要介绍一下HTTP
我们在网络的应用层中可以自己定义协议,但是,已经有大佬定义了一些现成的,非常好用的应用层协议,供我们直接使用,HTTP(超文本传输协议)就是其中之一。
在互联网世界中,HTTP(超文本传输协议)是一个至关重要的协议,他定义了客户端(如浏览器)与服务器之间如何进行通信,以交换或者传输超文本(比如HTML文档)。
HTTP协议是客户端与服务器之间通信的基础。客户端通过HTTP协议向服务器发送请求,服务器收到请求后处理并返回响应。HTTP协议是一个无连接、无状态的协议,即每次请求都需要建立新的连接,并且服务器不会保存客户端的状态信息。
1.2 认识URL
平时我们俗称的"网址"其实就是说的是URL(统一资源定位符)。
在网络通信中,网络通信都是IO操作的通信。当用户通过HTTP协议来获取的数据一般都在服务器中存储,我们需要通过特定的路径找到所请求的文件。那么为什么每一次使用HTTP协议去请求网页都要有网址呢?因为该网址上的信息是非常重要的,我们需要通过该网址上的信息找到我们所要访问的文件。
现在的问题是如何在庞大的互联网中标定一个文件的位置,在Linux中一切皆文件,在Linux系统中,所有文件都有其特定的路径,但是在不同的主机,有些文件可以有相同的路径,那么我们想要表示文件的唯一路径还需要在其前面添加该文件所在服务器的地址(IP + Port)。这样,我们就可以找到文件的唯一路径了。
再次回头看一看URL的组成(如下图所示):URL的部分有:协议方案名,登录信息(不需要),服务器地址,服务器端口号,带层次的文件路径,查询字符串,片段标识符。其中,我们最关心的是服务器地址和带层次的文件路径。
我们现在来理解一下查询字符串和片段标识符:
查询字符串用于在URL中传递数据,通常以
?
开头,后面跟着键值对,如?key=value
。片段标识符则以#
开头,表示网页中的一个具体位置或部分,例如#section1
。查询字符串用于传递参数,片段标识符用于指定浏览器显示的页面位置。
cpp
// 举个例子
https://cn.bing.com/search?q=dshfks&form=ANNTH1&refig=66dad2d0652448a28f0f3ec39a1b794f&pc=CNNDDB
1.3 urlencode和urldecode
在URL中避免不会出现一些特殊字符:/ ?: 等这样的字符,因为已经被URL当做了特殊意义理解了,因此这些字符不能随意地出现,比如,某个参数中需要带有这些特殊字符,就必须先对特殊字符进行转义。我们也可以使用专门的工具来看看特殊字符会转移成为什么?urlencode工具
转义的规则如下:将需要转码的字符转为16进制,然后从右向左取4位(不足4位直接处理),每2位做一位,前面加上%,编码成%XY格式。
cpp
例如:c++ ---> c%2B%2B
二、HTTP协议请求与响应格式
2.1 HTTP请求
- URL:指定服务器的什么资源,在网页地址中,出现的第一个文件分割符不一定是根目录,而是web根目录,可以是任何目录。
- 请求方法:GET,POST,HEAD,其中最重要的是GET和POST方法。
- HTTP版本:请求的是client的版本,一般是http/1.0 http/1.1 http/2.0
我们要来考虑两个问题:如何将报头和有效载荷进行分离;如何分用和交付?
如何将报头和有效载荷进行分离:空行可以保证我们把报头读完。content-length是正文长度,我们可以根据这个字段的长度来提取出报文中的正文。
如何进行分用和交付呢?因为是应用层,所以我们不需要进行分用,但是在还需要将数据进行交付给上层用户,交付的过程其实就是解包的过程。
2.2 HTTP响应
HTTP响应的报头和HTTP请求的报头的格式是类似的。
- HTTP版本:HTTP服务端的版本
- 状态码:HTTP协议中状态码分为五类:1XX 2XX 3XX 4XX 5XX,在下面讲解分别代表什么含义
- 状态码描述:解释状态码的含义
url默认我们指明了请求什么资源,HTTP协议可以支持默认首页,或者是一段Linux路径 /a/b/c.html。我们在一个网站中访问网页,进行页面跳转,每一次访问都是以HTTP请求!!!
什么是网站?站在程序员的视角中就是一对特定目录结构和文件构成的目录结构,所以我们写的HTTP 的服务器是后端,负责将特定目录下的特定资源(文件)发送给client IO程序!!一张网页中,可以包含很多资源,比如图片,获取一张完整的网页,先获取html,浏览器会发送多次请求获取网页中的所有元素,然后构成一个完整的网页结果。
三、HTTP的方法
|---------|-------------|-------------|
| 方法 | 说明 | 支持的HTTP协议版本 |
| GET | 获取资源 | 1.0 1.1 |
| POST | 传输实体主体 | 1.0 1.1 |
| PUT | 传输文件 | 1.0 1.1 |
| HEAD | 获得报文首部 | 1.0 1.1 |
| DELETE | 删除文件 | 1.0 1.1 |
| OPTIONS | 询问支持的方法 | 1.1 |
| TRACE | 追踪路径 | 1.1 |
| CONNECT | 要求用隧道协议连接代理 | 1.1 |
| LINK | 建立和资源之间的联系 | 1.0 |
| UNLINK | 断开连接关系 | 1.0 |
[HTTP的方法]
在这些方法中最常见的是GET方法和POST方法。
3.0 介绍一下表单
HTML表单用于收集用户的输入信息,HTML表单表示文档的一个区域,该区域包含交互控件,将用户收集到的信息发送到Web服务器上,GET和POST方法与其有关。
html
<form action="/" method="post">
<!-- 文本输入框 -->
<label for="name">用户名:</label>
<input type="text" id="name" name="name" required>
<br>
<!-- 密码输入框 -->
<label for="password">密码:</label>
<input type="password" id="password" name="password" required>
<br>
<!-- 单选按钮 -->
<label>性别:</label>
<input type="radio" id="male" name="gender" value="male" checked>
<label for="male">男</label>
<input type="radio" id="female" name="gender" value="female">
<label for="female">女</label>
<br>
<!-- 复选框 -->
<input type="checkbox" id="subscribe" name="subscribe" checked>
<label for="subscribe">订阅推送信息</label>
<br>
<!-- 下拉列表 -->
<label for="country">国家:</label>
<select id="country" name="country">
<option value="cn">CN</option>
<option value="usa">USA</option>
<option value="uk">UK</option>
</select>
<br>
<!-- 提交按钮 -->
<input type="submit" value="提交">
</form>
3.1 GET方法
- 用途:用于请求URL指定的资源,也可以用于提交参数。
- 报头示例:GET /index.html HTTP/1.1
- 特性:指定资源经服务器端解析后返回响应内容。
一般我们在使用网址时使用的方法是GET,在使用GET来提交参数的时候,我们需要将键值对数据转换为字符串的格式拼接到URL中。
3.2 POST方法
- 用途:用于传输实体的主体。通常用于提交表单数据
- 报头示例:POST /submit.html HTTP/1.1
- 特性:可以发送大量的数据给服务器,并且数据要包含在请求体中
POST用正文部分将请求提交参数,POST上传参数要比GET更私密,无论是GET还是POST数据都不安全。POST可以传递更大,更多的数据
3.3 PUT方法(不常用)
- 用途:用于传输文件,将请求报文主题中的文件保存到请求URL指定的位置
- 报头示例:PUT /example.html HTTP/1.1
- 特性:不经常使用,但是在某些情况下,比如RESTful API中,用于更新资源
3.4 HEAD方法(不常用)
- 用途:与GET方法类似,但是不返回报文主体部分,仅仅返回响应头
- 报头示例:HEAD /index.html HTTP/1.1
- 特性:用于确认URL的有效性以及资源更新的日期时间等
3.5 DELETE方法(不常用)
- 用途:用于删除文件,是PUT的相反方法
- 报头示例:DELETE /examplie.html /HTTP/1.1
- 特性:按请求URL删除指定的资源
3.6 OPTIONS方法(不常用)
- 用途:用于查询针对请求URL指定的资源支持的方法
- 报头示例:OPTIONS * HTTP/1.1
- 特性:返回允许的方法,比如GET、POST等
四、HTTP常见的Header
4.0 最常用的Header
cpp
Content-Type: 数据类型(text/html等)
Content-Length: Body的长度
Host: 客户端告知服务器,所请求的资源在哪个主机的哪个端口上
User-Agent: 声明用户的操作系统和浏览器版本信息
referer: 当前页面是从哪个页面跳转过来的
Location: 搭配3XX状态码使用,告诉客户端接下来要去哪里访问
Cookie: 用于在客户端存储少量的信息,通常用于实现会话(session)的功能
4.1 关于connection报头
HTTP中的Connection字段是HTTP报文头的一部分,它主要用于控制和管理客户端与服务器之间的连接状态
核心作用:
- 管理持久连接:Connection字段还用于管理持久连接(也称为长连接)。当客户端和服务器都不明确指定关闭连接时,连接将保持打开状态,以便在同一个连接上发送多个请求和接收多个响应。
- 持久连接(长连接):HTTP/1.1:在HTTP/1.1协议中,默认使用持久连接。当客户端和服务器都不明确指定关闭连接时,连接将保持打开状态,以便后续的请求和想用可以服用同一个连接。HTTP/1.0:在HTTP/1.0协议中,默认连接时非持久的。如果希望在HTTP/1.0上实现持久连接,需要在请求头中显示设置Connection: keep-alive.
语法格式:
- Connection:keep-alive:表示希望保持连接以复用TCP连接
- Connection:close:表示请求/想用完成后,应该关闭TCP连接
4.2 HTTP常见的header表格
|-----------------|-------------------------|---------------------------------------------------------------------------------------------------------------------------------|
| 字段名 | 含义 | 样例 |
| Accept | 客户端可接受的响应内容类型 | Accept: text/html,application/xhtml+xml,app lication/xml;q=0.9,image/webp,image /apng,*/*;q=0.8 |
| Accept-Encoding | 客户端支持的数据压缩格式 | Accept-Encoding:gzip, deflate, br |
| Accept-Language | 客户端可接收的语言类型 | Accept-Language: zhCN,zh;q=0.9,en;q=0.8 |
| Host | 请求的主机名和端口号 | Host: www.example.com:8080 |
| User-Agent | 客户端的软件环境信息 | User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/91.0.4472.124 Safari/537.36 |
| Cookie | 客户端发送给服务器的HTTP cookie信息 | Cookie: session_id=abcdefg12345; user_id=123 |
| Referer | 请求的来源URL | Referer: http://www.example.com/previous_pag e.html |
| Content-Type | 实体主体的媒体类型 | Content-Type: application/x-wwwform-urlencoded (对于表单提交) 或 Content-Type: application/json (对于 JSON 数据) |
| Content-Length | 实体主体的字节大小 | Content-Length: 150 |
| Authorization | 认证信息,如用户名和密码 | Authorization: Basic QWxhZGRpbjpvcGVuIHNlc2FtZQ== (Base64 编码后的用户名:密码) |
| Cache-Control | 缓存控制指令 | 请求时:Cache-Control: no-cache 或 Cache-Control: max-age=3600;响应 时:Cache-Control: public, maxage=360 |
| Connection | 请求完后是关闭还是保持连接 | Connection: keep-alive 或 Connection: close |
| Data | 请求或响应的日期和时间 | Date: Wed, 21 Oct 2023 07:28:00 GM |
| Location | 重定向的目标URL(与3XX状态码配合使用) | Location: http://www.example.com/new_location .html (与 302 状态码配合使用) |
| Server | 服务器类型 | Server: Apache/2.4.41 (Unix) |
| Last-Modified | 资源的最后修改时间 | Last-Modified: Wed, 21 Oct 2023 07:20:00 GMT |
| ETag | 资源的唯一标识符,用于缓存 | ETag: "3f80f-1b6-5f4e2512a4100" |
| Expires | 响应过期的日期和时间 | Expires: Wed, 21 Oct 2023 08:28:00 GMT |
五、HTTP的状态码(面试题)
5.1 状态码分类
|-----|----------|---------------|
| | 类别 | 原因短语 |
| 1XX | 信息性状态码 | 接收的请求正在处理 |
| 2XX | 成功状态码 | 请求正常处理完毕 |
| 3XX | 重定向状态码 | 需要进行附加操作以完成请求 |
| 4XX | 客户端错误状态码 | 服务器无法处理请求 |
| 5XX | 服务器错误状态码 | 服务器处理请求出错 |
最常见的状态码,比如200(OK)404(Not Found)302(Redirect,重定向)504(Bad Gateway)
5.2 重定向相关的状态码
我们来看一看关于重定向相关的状态码的表格:
|-----|--------------------|----------|-------------------------------|
| 状态码 | 含义 | 是否为临时重定向 | 应用样例 |
| 301 | Moved Permanently | 否(永久重定向) | 网站换域名后,自动跳转到新域名;搜索引擎更新网站链接时使用 |
| 302 | Found或SeeOther | 是(临时重定向) | 用户登录成功后,重定向到用户首页 |
| 307 | Temporary Redirect | 是(临时重定向) | 临时重定向资源到新的位置(较少使用) |
| 308 | Permanent Redirect | 否(永久重定向) | 永久重定向资源到新的位置(较少使用) |
关于重定向的验证,我们可以使用301和302为代表:
HTTP状态码301(永久重定向)和302(临时重定向)都依赖Location选项。以下是关于两者依赖Location选项的详细说明。
5.2.1 HTTP状态码301(永久重定向)
当服务器返回HTTP301状态码时,表示请求的资源已经被永久移动到新的位置。
在这种情况下,服务器会在响应中添加一个Location头部,用于指定资源的新位置。这个Location头部包含了新的URL地址,浏览器会自动重定向到该地址。
例如,在HTTP响应中,可能会看到类似于以下的头部位置:
cpp
HTTP/1.1 301 Moved Permanently\r\n
Location: https://www.new-url.com\r\n
5.2.2 HTTP状态码302(临时重定向)
当服务器返回HTTP302状态码时,表示请求的资源临时被移动到新的位置。
同样地,服务器也会在响应中添加一个Location头部来指定资源的新位置。浏览器会暂时使用新的URL进行后续的请求,但不会缓存这个重定向。
例如,在HTTP响应中,可能会看到类似于以下的头部信息:
cpp
HTTP/1.1 302 Found\r\n
Location: https://www.new-url.com\r\n
**总结:**无论是HTTP301还是HTTP302重定向,都需要一栏Location选项来指定资源的新位置。这个Location选项是一个标准的HTTP响应头部,用于告诉浏览器应该将请求重定向到哪个新的URL地址。