在前面的文章中我们自己定义并实现了一个自定义协议,从序列化和反序列化,到封装报文,解析报文等,这就是我们自己实现的一个应用层协议。虽然我们说, 应用层协议是我们程序员自己定的,但实际上,已经有大佬们定义了一些现成的,又非常好用的应用层协议,供我们直接参考使用,
HTTP(超文本传输协议)就是其中之一,所以下面我们就来认识一下
HTTP(HyperText Transfer Protocol,超文本传输协议)是互联网中最重要的应用层协议之一。它定义了客户端(如浏览器)与服务器之间进行通信的规则和格式,主要用于传输超文本(如HTML文档)以及其他网络资源。
简单来说,HTTP 定义了客户端(通常是 Web 浏览器)和服务器之间如何通信。它规定了客户端可以发送哪些请求,以及服务器应该返回哪些响应
核心特点
HTTP协议的发展是一部为了满足日益增长的网络需求而不断自我革新的历史。每一次升级都旨在解决前一版本的性能瓶颈和安全问题。
URL(Uniform Resource Locator,统一资源定位符),通俗地说,它就是我们在互联网上访问一个网站、一张图片、一个视频或其他任何资源时,在浏览器地址栏里输入的“网址”。
它是一个标准化的地址系统,告诉浏览器如何在浩瀚的互联网上精确地找到并访问特定的资源。
URL 是 URI 的一个子集。URI 是一个更广泛的概念,用于标识一个资源,而 URL 不仅标识资源,还提供了定位和访问它的方式。在日常交谈中,两者常常混用。
一个完整的 URL 由多个部分组成,每个部分都有其特定的含义。其标准格式如下:
[协议] :// [主机名] : [端口] / [路径] ? [查询字符串] # [片段]让我们用一个具体的例子来分解它:
https://www.example.com:443/products/index.html?category=electronics&page=2#reviewshttps:
这部分通常包括主机名、端口,有时还包含用户名和密码。
www.example.com
www
example
.com
:443
/products/index.html
?category=electronics&page=2
#reviews
由于 URL 只能使用 ASCII 字符集中的一组有限字符(字母、数字和少数符号),如果 URL 中包含不在此范围内的字符(如中文、空格、特殊符号),就必须进行 URL 编码。
%20 或 + (编码为+并不是标准的 URL 编码方式,而是 特定上下文中的特殊约定)。
中国”在 UTF-8 编码下会被编码为 %E4%B8%AD%E5%9B%BD。
& 编码为 %26,? 编码为 %3F。
示例:
一个未编码的 URL:https://example.com/search?q=hello world&lang=zh-CN
编码后的 URL:https://example.com/search?q=hello%20world&lang=zh-CN
例如:

上图中 “+” 被转义成了 “%2B”
注意:URLDecode是URLEncode的逆过程,将编码后的字符恢复为原始字符
下面推荐一个编码解码的网站
一个 HTTP 请求由以下部分组成:

示例:

一个 HTTP 响应由以下部分组成:

示例:

那怎么将报文中的报头和报文有效分离出来呢?怎么完整读取到一个报文呢?
在HTTP协议中,报文分为请求报文和响应报文。两者格式类似,都由起始行、头部(Header)和主体(Body)组成。头部和主体之间通过一个空行(即连续的\r\n\r\n)来分隔。
要分离报头和报文主体,我们需要:
但是,需要注意的是,HTTP报文可能使用分块传输编码(Transfer-Encoding: chunked)或者有Content-Length头部来指示主体长度。因此,完整读取一个报文可能需要根据这些头部信息来确定主体的长度。
以下是一个基本的步骤:
步骤1:读取数据直到遇到空行,这样我们就可以先解析头部。
步骤2:解析头部,获取重要的头部字段,如Content-Length或Transfer-Encoding。
步骤3:根据头部信息,读取主体部分:
如果存在Content-Length,则读取指定长度的字节。
如果是分块编码,则需要按照分块编码的规则读取,直到遇到一个长度为0的块。
如果既没有Content-Length也不是分块编码,那么主体可能直到连接关闭为止(例如,HTTP/1.0的持续连接关闭时表示主体结束)。
方法 | 描述 | 幂等性 | 安全性 |
|---|---|---|---|
GET | 获取资源。只应用于请求数据,不应产生副作用。 | 是 | 是 |
POST | 创建新资源或提交数据(如表单、文件上传)。 | 否 | 否 |
PUT | 更新/替换一个已存在的资源。 | 是 | 否 |
PATCH | 部分更新一个资源。 | 否 | 否 |
DELETE | 删除指定的资源。 | 是 | 否 |
HEAD | 与 GET 类似,但只获取响应头,不获取响应体。用于检查资源是否存在等。 | 是 | 是 |
OPTIONS | 用于描述目标资源的通信选项(如服务器支持哪些方法)。 | 是 | 是 |
幂等性:同样的请求执行一次与连续执行多次,对服务器资源的状态改变是相同的。 安全性:该方法不应改变服务器资源的状态。
其中最常用的就是GET方法和POST方法.
定义:
特点:
示例:
GET /api/users?id=123 HTTP/1.1
Host: example.com注意:
定义:
特点:
示例:
POST /api/users HTTP/1.1
Host: example.com
Content-Type: application/json
Content-Length: 38
{"name": "Alice", "email": "alice@example.com"}适用场景:

最常见的状态码,比如 200(OK), 404(Not Found), 403(Forbidden), 302(Redirect, 重定向), 504(BadGateway)
2xx 成功
3xx 重定向
4xx 客户端错误
5xx 服务器错误
以下是仅包含重定向相关状态码的表格:
状态码 | 含义 | 是否为临时重定向 | 应用样例 |
|---|---|---|---|
301 | Moved Permanently | 否(永久重定向) | 网站换域名后,自动跳转到新域名;搜索引擎更新网站链接时使用 |
302 | Found 或 See Other | 是(临时重定向) | 用户登录成功后,重定向到用户首页 |
307 | Temporary Redirect | 是(临时重定向) | 临时重定向资源到新的位置(较少使用) |
308 | Permanent Redirect | 否(永久重定向) | 永久重定向资源到新的位置(较少使用) |
关于重定向的验证,以301为代表
HTTP状态码301(永久重定向)和302(临时重定向)都依赖Location选项。以下是关于两者依赖Location选项的详细说明:
HTTP状态码301(永久重定向)
HTTP/1.1 301 Moved Permanently\r\n
Location: https://www.new-url.com\r\nHTTP状态码302(临时重定向)
HTTP/1.1 302 Found\r\n
Location: https://www.new-url.com\r\n总结:无论是HTTP 301还是HTTP 302重定向,都需要依赖Location选项来指定资源的新位置。这个Location选项是一个标准的HTTP响应头部,用于告诉浏览器应该将请求重定向到哪个新的URL地址。
关于connection报头
HTTP中的 Connection 字段是HTTP报文头的一部分,它主要用于控制和管理客户端与服务器之间的连接状态
核心作用
持久连接(长连接)
Connection: keep-alive 。语法格式
Connection: keep-alive :表示希望保持连接以复用TCP连接。Connection: close :表示请求/响应完成后,应该关闭TCP连接。下面附上一张关于HTTP常见header的表格
字段名 | 含义 | 样例 |
|---|---|---|
Accept | 客户端可接受的响应内容类型 | Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,image/apng,/;q=0.8 |
Accept-Encoding | 客户端支持的数据压缩格式 | Accept-Encoding: gzip, deflate, br |
Accept-Language | 客户端可接受的语⾔类型 | Accept-Language: zh-CN,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_page.html |
Content-Type | 实体主体的媒体类型 | Content-Type: application/x-www-formurlencoded (对于表单提交) 或 Content-Type:application/json (对于JSON数据) |
Content-Length | 实体主体的字节大小 | Content-Length: 150 |
Authorization | 认证信息,如用户名和密码 | Authorization: Basic QWxhZGRpbjpvcGVuIHNlc2FtZQ== (Base64编码后的用户名:密码) |
Cache-Control | 缓存控制指令 | 请求时: Cache-Control: no-cache 或 CacheControl: max-age=3600 ;响应时: CacheControl: public, max-age=3600 |
Connection | 请求完后是关闭还是保持连接 | Connection: keep-alive 或 Connection: close |
Date | 请求或响应的日期和时间 | Date: Wed, 21 Oct 2023 07:28:00 GMT |
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 |