一、引言
每天打开浏览器刷网页、登录账号、下载文件,这些看似稀松平常的操作背后,都有一个默默无闻的协议在支撑------它就是HTTP。作为应用层最重要的协议之一,HTTP可以说是整个Web世界的基石。
很多同学在学习计算机网络的时候,总觉得HTTP"很简单"------++不就是请求响应吗?不就是GET和POST吗?但真到了面试被问起"GET和POST到底有什么本质区别"、"HTTP长连接和短连接的区别"、"Cookie和Session是怎么工作的++ "这些问题时,往往又答得支支吾吾,知其然而不知其所以然。
这篇文章将从协议格式入手,逐层拆解HTTP的核心机制,不仅会讲清楚"是什么",更会解释"为什么"。最后我们还会用C语言从零实现一个最简单的HTTP服务器,只有亲手写过一遍,才能真正理解协议的本质。
二、HTTP协议
HTTP的全称是HyperText Transfer Protocol****,超文本传输协议。这里的"超文本"指的不仅仅是文本,还包括HTML、图片、音频、视频、CSS等各种资源。它定义了客户端和服务器之间通信的格式和规则,使得不同厂商开发的浏览器和服务器能够互相通信。
2.1 特点
HTTP协议有两个重要的特性,也是面试经常考察的点:
1. 无连接
HTTP早期版本采用的是"请求-应答"模式,每次连接只处理一个请求。服务器处理完客户端的请求并收到应答后,就会断开连接。
这种设计在早期互联网内容简单、网页只有纯文本的时候是足够的,但随着网页内容越来越丰富,一个页面可能包含几十上百个资源,每次都要重新建立TCP连接的开销就变得难以接受了。所以HTTP/1.1引入了长连接机制,这个后面会详细讲。
2. 无状态
HTTP协议本身不会对请求和响应之间的通信状态进行保存。也就是说,服务器不知道客户端之前发过什么请求,每一个请求都是完全独立的。
这个特性有好有坏:好处是服务器不需要维护状态,实现简单,扩展性好;
坏处是如果需要保持用户登录状态、购物车这类功能,就需要额外的机制(Cookie和Session)来实现。
很多人会把"无连接"和"无状态"搞混。简单来说:无连接是指连接会不会复用的问题,无状态是指服务器记不记得你的问题。这是两个完全不同的维度。
2.2 通信模型
HTTP永远是客户端发起请求,服务器回送响应。服务器永远不会主动给客户端发消息,这是一个非常重要的模型。
这种请求-响应模型决定了HTTP天然是"拉"模式的协议,客户端想要什么就主动去拉。如果需要实现服务器主动推送,就需要WebSocket或者HTTP/2的Server Push这类技术了。
三、URL
我们平时说的"网址",其实就是URL(统一资源定位符)。URL是互联网上标准资源的地址,它告诉浏览器资源在哪里,以及用什么方式去访问。一个完整的URL结构如下图所示:

我们来逐一拆解每个部分:
-
协议方案名 :也就是访问资源使用的协议,最常见的是http和https,还有ftp、file等其他协议。
-
登录信息 :这部分现在已经很少见了,格式是 user:pass@ ,用来指定用户名和密码进行认证,因为安全性问题基本被淘汰了。
-
服务器地址:可以是域名,也可以是IP地址。
-
服务器端口号:如果是协议默认端口可以省略,HTTP默认80,HTTPS默认443。
-
带层次的文件路径:服务器上资源的路径,对应服务器上的文件或者路由。
-
查询字符串 :以 ? 开头,以 &分隔的键值对,用来给服务器传递参数,比如 ?uid=1。
-
片段标识符 :以 # 开头,用来定位页面内的某个位置,比如锚点,这部分是不会发送给服务器的,只有浏览器自己处理。
3.1 urlencode与urldecode
不知道大家有没有注意过,当你在百度搜索 "C++" 的时候,地址栏里显示的是 "c%2B%2B" 而不是直接显示"C++"。这是为什么呢?
因为像 /、?、:、@、=、&、+这些字符,在URL里是有特殊含义的。如果参数里本身就包含这些字符,就会产生歧义。比如你想传一个参数 "a=1&b=2" 作为值,那里面的&就会被当成参数分隔符。这时候就需要对特殊字符进行转义,也就是urlencode。
转义规则很简单:将需要转码的字符转为UTF-8编码的16进制,然后每两位前面加一个%。比如:
-
"+"的ASCII码是43,16进制是2B,所以转义后是%2B
-
空格的ASCII码是32,16进制是20,所以转义后是%20,或者也可以编码成+
-
中文的话会先转成UTF-8编码,每个字节都加%,比如"你"的UTF-8编码是E4 BD A0,所以转义后是%E4%BD%A0
*urldecode就是urlencode的逆过程,服务器收到转义后的字符串,会自动还原成原来的字符。*各种编程语言都提供了对应的urlencode和urldecode函数,平时我们不需要自己手动实现,但一定要知道有这么回事。

四、HTTP请求报文
HTTP是一个文本协议,也就是说它的报文是纯ASCII文本,不是二进制的,这也是为什么我们可以直接用telnet或者nc去连接HTTP服务器,手动输入请求就能拿到响应。一个标准的HTTP请求报文由四部分组成:请求行、请求报头、空行、请求正文**。**

我们来看一个真实的POST请求例子,这是从西安交通大学就业网抓包拿到的登录请求:

4.1 请求行
请求行是请求的第一行,格式是:请求方法 + 空格 + URL + 空格 + HTTP版本 + 换行符
比如上面的例子中,请求方法是POST,URL是系统登录---西安交通大学就业管理服务平台,HTTP版本是1.1。
4.2 请求报头
请求行之后就是请求报头,是一系列键值对,格式是 Key: Value,每一对之间用\r\n分隔。这些头部信息告诉服务器关于客户端和请求的各种元信息:
-
Host:指定要访问的服务器主机名和端口,这个在HTTP/1.1里是必须的,因为一台服务器上可能部署多个网站,需要靠Host来区分
-
Content-Length:请求正文的长度,单位是字节。服务器根据这个值来确定要读取多少字节的正文
-
Content-Type:请求正文的数据格式,比如application/x-www-form-urlencoded表示是表单数据,application/json表示是JSON数据
-
User-Agent:客户端的身份信息,告诉服务器客户端是什么浏览器、什么操作系统
-
Cookie:客户端存储的Cookie信息,用来维持状态
-
Referer:这个请求是从哪个页面跳转过来的
-
Accept:客户端能接受哪些类型的响应内容
-
Accept-Encoding:客户端支持哪些压缩算法,比如gzip、deflate
-
Accept-Language:客户端偏好的语言
-
Connection:连接管理,keep-alive表示希望复用长连接
4.3 空行
请求报头结束之后,会有一个空行,这个空行非常重要,它告诉服务器:"头部到此为止了,后面的就是正文了"。服务器解析请求的时候,就是读到空行就知道头部结束了。
4.4 请求正文
空行之后就是请求正文了。GET请求的正文一般是空的,因为参数都放在URL的查询字符串里了。
POST请求的参数一般放在正文里。
很多初学者会问:GET请求能不能带Body?其实规范上并没有禁止GET带Body,但HTTP标准没有定义GET请求的Body应该怎么处理,很多服务器、代理、CDN都会直接忽略GET请求的Body,所以实际开发中永远不要给GET请求加Body,这是约定俗成的规范。
五、HTTP响应报文
服务器收到请求并处理之后,会返回HTTP响应报文。响应报文的结构和请求非常类似,也是四部分:状态行、响应报头、空行、响应正文。
| 结构 | 内容 | 说明 |
|---|---|---|
| 状态行 | HTTP版本 + 空格 + 状态码 + 空格 + 状态码描述 + 换行符 | 比如HTTP/1.1 200 OK |
| 响应报头 | Key: Value + 换行符 | 和请求头类似,是服务器返回的元信息 |
| 响应报头 | Key: Value + 换行符 | 和请求头类似,是服务器返回的元信息 |
| 响应报头 | ... + 换行符 | 和请求头类似,是服务器返回的元信息 |
| 空行 | 换行符 | 分隔头部和正文 |
| 响应正文 | DATA | 实际返回的数据,可能是HTML、JSON、图片等 |
响应案例:

5.1 状态行
状态行是响应的第一行,格式是:HTTP版本 + 空格 + 状态码 + 空格 + 状态码描述 + 换行符
状态码是三位数字,告诉客户端请求处理的结果。状态码描述只是给人看的,程序只看状态码。比如200 OK,404 Not Found这些都是常见的状态码,后面会详细讲。
5.2 响应报头
响应报头也是键值对,和请求头类似,但字段不太一样。常见的响应头有:
-
Content-Type:响应正文的类型,比如text/html是HTML页面,application/json是JSON数据,image/jpeg是JPEG图片
-
Content-Length:响应正文的长度,如果是分块传输就没有这个字段
-
Content-Encoding:正文使用的压缩算法,比如gzip
-
Server:服务器软件信息,比如nginx、Apache
-
Set-Cookie:让浏览器设置Cookie
-
Location:配合3xx状态码做重定向
-
Cache-Control:缓存控制
5.3 空行和响应正文
和请求一样,空行用来分隔头部和正文。空行之后就是实际返回的数据,可能是HTML页面、JSON、图片等等。浏览器拿到正文之后,会根据Content-Type来决定怎么渲染这个内容。

六、HTTP请求方法
HTTP定义了很多请求方法,用来表明对资源要做什么操作。
HTTP/1.0定义了GET、POST、HEAD三种方法,HTTP/1.1又新增了OPTIONS、PUT、DELETE、TRACE、CONNECT五种方法。我们最常用的就是GET和POST,其他方法了解即可。

6.1 GET方法
用途:用于请求URL指定的资源。
示例:GET /index.html HTTP/1.1
特性:指定资源经服务器端解析后返回响应内容。
form表单 :HTML 表单 | 菜鸟教程
std::string GetFileContentHelper(const std::string &path)
{
// 一份简单的读取二进制文件的代码
std::ifstream in(path, std::ios::binary);
if (!in.is_open())
return "";
in.seekg(0, in.end);
int filesize = in.tellg();
in.seekg(0, in.beg);
std::string content;
content.resize(filesize);
in.read((char *)content.c_str(), filesize);
// std::vector<char> content(filesize);
// in.read(content.data(), filesize);
in.close();
return content;
}
6.2 POST方法
用途:用于传输实体的主体,通常用于提交表单数据。
示例:POST /submit.cgi HTTP/1.1
特性:可以发送大量的数据给服务器,并且数据包含在请求体中。
form表单 :HTML 表单 | 菜鸟教程
6.3 区别
这是面试最常考的问题之一,很多人只会背"GET参数在URL,POST参数在Body"、"GET比POST安全"这种表面答案,但其实这都不是本质区别。我们来从多个角度对比一下:
| 对比维度 | GET | POST |
|---|---|---|
| 语义 | 获取/查询资源(只读) | 提交/创建/修改资源(会改变服务器状态) |
| 幂等性 | 幂等(多次请求结果相同) | 非幂等(多次提交可能产生多个资源,比如重复下单) |
| 安全性 | 安全(不会改变服务器状态) | 不安全(会修改服务器上的资源) |
| 参数位置 | URL查询字符串 | 请求正文 |
| 参数长度 | 受URL长度限制(一般几KB) | 理论上无限制 |
| 缓存 | 可以被浏览器缓存、收藏为书签 | 不会被缓存,不能收藏为书签 |
| 数据包 | 一般一个TCP数据包发完(请求头+数据一起发) | 可能分两个数据包:先发请求头,服务器返回100 Continue再发正文 |
| 编码类型 | application/x-www-form-urlencoded | 支持多种编码(form-data、json等) |
关于"POST比GET安全"这个说法是不准确的。POST的参数在Body里,不会直接显示在地址栏、历史记录、服务器日志里。HTTP是明文传输的,不管是GET还是POST,抓包都能直接看到参数。想要真正安全,必须用HTTPS加密。
6.4 其他方法
6.4.1 PUT方法
用途:用于传输文件,将请求报文主体中的文件保存到请求URL指定的位置。
示例:PUT /example.html HTTP/1.1
特性:不太常用,但在某些情况下,如RESTful API中,用于更新资源。
6.4.2 HEAD方法
用途:与GET方法类似,但不返回报文主体部分,仅返回响应头。
示例:HEAD /index.html HTTP/1.1
特性:用于确认URL的有效性及资源更新的日期时间等。
# curl -i 显示响应头和响应体
$ curl -i www.baidu.com
HTTP/1.1 200 OK
Accept-Ranges: bytes
Cache-Control: private, no-cache, no-store, proxy-revalidate, no-transform
Connection: keep-alive
Content-Length: 2381
Content-Type: text/html
Date: Sun, 16 Jun 2024 08:38:04 GMT
Etag: "588604dc-94d"
Last-Modified: Mon, 23 Jan 2017 13:27:56 GMT
Pragma: no-cache
Server: bfe/1.0.8.18
Set-Cookie: BDORZ=27315; max-age=86400; domain=.baidu.com; path=/
<!DOCTYPE html>
...
# 使用HEAD方法,只会返回响应头
$ curl --head www.baidu.com
HTTP/1.1 200 OK
Accept-Ranges: bytes
Cache-Control: private, no-cache, no-store, proxy-revalidate, no-transform
Connection: keep-alive
Content-Length: 277
Content-Type: text/html
Date: Sun, 16 Jun 2024 08:43:38 GMT
Etag: "575e1f71-115"
Last-Modified: Mon, 13 Jun 2016 02:50:25 GMT
Pragma: no-cache
Server: bfe/1.0.8.18
6.4.3 DELETE方法
用途:用于删除文件,是PUT的相反方法。
示例:DELETE /example.html HTTP/1.1
特性:按请求URL删除指定的资源。
6.4.4 OPTIONS方法
用途:用于查询针对请求URL指定的资源支持的方法。
示例:OPTIONS * HTTP/1.1
特性:返回允许的方法,如GET、POST等。
七、HTTP状态码
状态码是服务器对请求的回应,用三位数字表示。第一位数字定义了响应的类别,一共分为5大类:

我们不需要记住所有状态码,但常见的一定要熟悉,这不仅是面试考点,也是开发中排查问题的基础。
7.1 常见状态码
(1) 2xx 成功类
-
200 OK:最常见的状态码,表示请求成功,正常返回了数据。
-
201 Created:请求成功并且服务器创建了新的资源,一般在POST创建资源时返回。
-
204 No Content:请求成功,但没有返回任何内容。比如删除操作成功后,不需要返回什么数据,就可以返回204。
(2)3xx 重定向类
-
301 Moved Permanently:永久重定向。资源被永久移动到了新位置,搜索引擎会更新索引,浏览器会缓存这个重定向。
-
302 Found:临时重定向。资源临时在别的位置,以后还可能变。
-
304 Not Modified:资源未修改,客户端可以使用本地缓存。这是浏览器缓存机制的重要部分,。
-
307 Temporary Redirect:和302类似,也是临时重定向,但区别是307不允许改变请求方法。
这里301和302的区别:
| 状态码 | 重定向类型 | 是否缓存 | 请求方法是否改变 | 典型场景 |
|---|---|---|---|---|
| 301 | 永久重定向 | 浏览器会永久缓存 | 可能改变(POST变GET) | 网站换域名、HTTP升级HTTPS |
| 302 | 临时重定向 | 不缓存 | 可能改变(POST变GET) | 登录后跳转首页、临时维护页面 |
| 307 | 临时重定向 | 不缓存 | 不改变 | 需要保持POST请求的场景 |
| 308 | 永久重定向 | 浏览器缓存 | 不改变 | 需要保持请求方法的永久重定向 |
不管是301还是302,都需要配合Location响应头来告诉浏览器要跳转到哪个地址。比如:
HTTP/1.1 302 Found
Location: https://www.new-url.com/login
Content-Length: 0
(3)4xx 客户端错误类
-
400 Bad Request:请求报文有语法错误,服务器无法理解。比如参数格式不对、JSON解析失败。
-
401 Unauthorized:未认证,需要登录才能访问。注意这个是"未认证"而不是"未授权",名字起得有点误导。
-
403 Forbidden:服务器拒绝访问,权限不够。比如你登录了普通用户账号,想访问管理员页面,就会返回403。
-
404 Not Found:最有名的状态码,服务器上找不到你请求的资源。地址写错了、资源被删了都会出现404。
-
405 Method Not Allowed:请求方法不被允许。比如一个接口只支持POST,你用GET去请求,就会返回405。
(4)5xx 服务器错误类
-
500 Internal Server Error:服务器内部错误,一般是代码出bug了,比如数据库连不上、空指针异常、程序崩溃。
-
502 Bad Gateway:网关错误,代理服务器从上游服务器收到了无效的响应。比如Nginx反向代理,后端服务挂了,Nginx就会返回502。
-
503 Service Unavailable:服务器暂时不可用,一般是维护或者过载了。比如服务器正在重启,或者流量太大扛不住了。
-
504 Gateway Timeout:网关超时,代理服务器等上游服务器的响应等太久了,超时了。
小技巧:看到状态码先看第一位数字,2开头就是成功,3开头就是跳转,4开头就是客户端的锅,5开头就是服务器的锅。这样排查问题的时候就能快速定位方向了。
八、HTTP Header
Header是HTTP报文的重要组成部分,它携带了很多关键信息。我们不可能记住所有Header,但常用的一定要理解。这里挑最重要的几个详细讲。
8.1 实体相关Header
-
Content-Type:非常重要的Header,指定了Body的数据格式。浏览器会根据这个值来解析Body内容。常见的取值:
-
text/html:HTML文档
-
text/css:CSS样式表
-
application/javascript:JavaScript代码
-
application/json:JSON数据
-
application/x-www-form-urlencoded:普通表单提交的数据,格式和URL查询字符串一样
-
multipart/form-data:包含文件上传的表单数据
-
image/jpeg、image/png:图片资源
-
-
Content-Length:Body的长度,单位是字节。服务器根据这个值来确定要读取多少数据。
-
Content-Encoding:Body使用的压缩算法,最常见的是gzip。
8.2 请求相关Header
-
Host:HTTP/1.1必须携带的Header,指定请求的主机名和端口。
-
User-Agent:告诉服务器客户端的信息,包括浏览器类型、版本、操作系统等。很多网站会根据UA来判断你是PC还是手机,然后返回不同的页面。
-
Referer:告诉服务器这个请求是从哪个页面跳转过来的。注意这个单词拼错了,正确的拼写应该是Referrer,但是标准写错了,将错就错一直用到现在。
-
Accept:客户端能接受的媒体类型,用q值表示权重,比如q=0.9表示优先级0.9。
-
Accept-Encoding:客户端支持的压缩算法,比如gzip, deflate, br。
-
Accept-Language:客户端偏好的语言,比如zh-CN表示中文,en表示英文。
8.3 连接管理Header
Connection字段用来管理TCP连接是否复用。
-
Connection: keep-alive:告诉对方这个TCP连接不要关闭,后面的请求还要复用这个连接,也就是长连接。HTTP/1.1默认就是长连接。
-
Connection: close:告诉对方请求处理完就关闭连接。HTTP/1.0默认是短连接,每次请求完就关闭。
长连接的好处:长连接只需要建立一次TCP连接,就可以在上面传输多个请求响应,大大减少了握手开销和延迟。
长连接的坏处:服务器要维护大量打开的连接,每个连接都占用文件描述符和内存。所以一般服务器都会配置长连接超时时间。
8.4 其他重要Header
-
Cookie:客户端把Cookie发给服务器,用来维持状态,下一节详细讲。
-
Set-Cookie:服务器让浏览器设置Cookie。
-
Location:配合3xx状态码做重定向,指定目标URL。
-
Cache-Control:控制缓存策略,比如max-age=3600表示缓存3600秒,no-cache表示不缓存。
-
Server:服务器软件信息,比如nginx/1.18.0。
九、实现一个HTTP服务器
说一千道一万,不如亲手写一遍。HTTP协议本质上就是TCP连接上传输的符合特定格式的文本,我们完全可以用最基础的Socket API来实现一个最简单的HTTP服务器。
我们用C语言来写,整个服务器代码不到60行,就能在浏览器里显示"hello world"。
cpp
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <unistd.h>
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
void Usage() {
printf("usage: ./server [ip] [port]\\n");
}
int main(int argc, char* argv[]) {
if (argc != 3) {
Usage();
return 1;
}
// 1. 创建TCP套接字
int listen_fd = socket(AF_INET, SOCK_STREAM, 0);
if (listen_fd < 0) {
perror("socket");
return 1;
}
// 2. 绑定IP和端口
struct sockaddr_in addr;
addr.sin_family = AF_INET;
addr.sin_addr.s_addr = inet_addr(argv[1]);
addr.sin_port = htons(atoi(argv[2]));
int ret = bind(listen_fd, (struct sockaddr*)&addr, sizeof(addr));
if (ret < 0) {
perror("bind");
return 1;
}
// 3. 开始监听
ret = listen(listen_fd, 10);
if (ret < 0) {
perror("listen");
return 1;
}
printf("Server started on http://%s:%s\\n", argv[1], argv[2]);
// 4. 循环接受连接
for (;;) {
struct sockaddr_in client_addr;
socklen_t len = sizeof(client_addr);
int client_fd = accept(listen_fd, (struct sockaddr*)&client_addr, &len);
if (client_fd < 0) {
perror("accept");
continue;
}
// 5. 读取请求(这里简单读取,不做解析)
char input_buf[1024 * 10] = {0};
ssize_t read_size = read(client_fd, input_buf, sizeof(input_buf) - 1);
if (read_size > 0) {
printf("[Request]\\n%s\\n", input_buf);
}
// 6. 构造HTTP响应
const char* body = "<h1>hello world</h1>";
char response[1024] = {0};
sprintf(response,
"HTTP/1.0 200 OK\\r\\n"
"Content-Type: text/html\\r\\n"
"Content-Length: %lu\\r\\n"
"\\r\\n"
"%s",
strlen(body), body
);
// 7. 发送响应
write(client_fd, response, strlen(response));
// 8. 关闭连接
close(client_fd);
}
close(listen_fd);
return 0;
}
TCP服务器流程:socket -> bind -> listen -> accept -> read -> write -> close。构造响应字符串的时候要按照HTTP协议格式:状态行 + 响应头 + 空行 + 正文。
我们来编译运行一下:
bash
$ gcc server.c -o server
$ ./server 0.0.0.0 9090
Server started on http://0.0.0.0:9090
然后打开浏览器,输入http://127.0.0.1:9090,就能看到页面上显示"hello world"了!同时服务器终端会打印出浏览器发来的请求:

十、HTTP协议演进
HTTP(Hypertext Transfer Protocol,超文本传输协议)作为互联网中浏览器和服务器间通信的基石,经历了从简单到复杂、从单一到多样的发展过程。以下将按照时间顺序,介绍HTTP的主要版本、核心技术及其对应的时代背景。
| 版本 | 发布时间 | 核心特性 | 解决的痛点 |
|---|---|---|---|
| HTTP/0.9 | 1991年 | 只支持GET,只有HTML,没有头部,没有状态码 | 最初只用来传输简单的超文本文档 |
| HTTP/1.0 | 1996年 | 增加POST、HEAD方法,有头部,支持多种内容类型,状态码,缓存 | 网页内容开始丰富,需要传输图片等不同类型资源 |
| HTTP/1.1 | 1999年 | 长连接,管道化,Host头,分块传输,更多方法 | HTTP/1.0每次请求都新建连接,性能太差 |
| HTTP/2 | 2015年 | 二进制分帧,多路复用,头部压缩,服务器推送 | HTTP/1.1队头阻塞,头部冗余太大 |
| HTTP/3 | 2022年 | 基于QUIC协议(UDP),0-RTT握手,解决TCP队头阻塞 | TCP协议本身的队头阻塞问题,握手延迟高 |
10.1 HTTP/0.9
(1)核心技术
-
仅支持GET请求方法。
-
仅支持纯文本传输,主要是HTML格式。
-
无请求和响应头信息。
(2)时代背景
-
1991年,HTTP/0.9版本作为HTTP协议的初始版本,用于传输基本的超文本HTML内容。
-
当时的互联网还处于起步阶段,网页内容相对简单,主要以文本为主。
10.2 HTTP/1.0
(1)核心技术
-
引入POST和HEAD请求方法。
-
请求和响应头信息,支持多种数据格式。
-
支持缓存。
-
状态码、多字符集支持等。
(2)时代背景
-
1996年,随着互联网的快速发展,网页内容逐渐丰富,HTTP/1.0版本应运而生。
-
为了满足日益增长的网络应用需求,HTTP/1.0增加了更多的功能和灵活性。
-
然而,HTTP/1.0的工作方式是每次TCP连接只能发送一个请求,性能上存在一定局限。
10.3 HTTP/1.1
(1)核心技术
-
引入持久连接,支持管道化)。
-
允许在单个TCP连接上进行多个请求和响应,提高了性能。
-
引入分块传输编码。
-
支持Host头,允许在一个IP地址上部署多个Web站点。
(2)时代背景
-
1999年,随着网页加载的外部资源越来越多,HTTP/1.0的性能问题愈发突出。
-
HTTP/1.1通过引入持久连接和管道化等技术,有效提高了数据传输效率。
-
同时,互联网应用开始呈现出多元化、复杂化的趋势,HTTP/1.1的出现满足了这些需求。
10.4 HTTP/2.0
(1)核心技术
-
多路复用,一个TCP连接允许多个HTTP请求。
-
二进制帧格式,优化数据传输。
-
头部压缩,减少传输开销。
-
服务器推送,提前发送资源到客户端。
(2)时代背景
-
2015年,随着移动互联网的兴起和云计算技术的发展,网络应用对性能的要求越来越高。
-
HTTP/2.0通过多路复用、二进制帧格式等技术,显著提高了数据传输效率和网络性能。
-
同时,HTTP/2.0还支持加密传输,提高了数据传输的安全性。
10.5 HTTP/3.0
(1)核心技术
-
使用QUIC协议替代TCP协议,基于UDP构建的多路复用传输协议。
-
减少了TCP三次握手及TLS握手时间,提高了连接建立速度。
-
解决了TCP中的线头阻塞问题,提高了数据传输效率。
(2)时代背景:
-
2022年,随着5G、物联网等技术的快速发展,网络应用对实时性、可靠性的要求越来越高。
-
HTTP/3.0通过使用QUIC协议,提高了连接建立速度和数据传输效率,满足了这些需求。
-
同时,HTTP/3.0还支持加密传输,保证了数据传输的安全性。
十一、总结
到这里,HTTP协议的核心知识点就讲得差不多了。我们从URL格式、请求响应报文结构,到请求方法、状态码、Header,最后动手实现了一个简单的HTTP服务器,还梳理了HTTP从0.9到3.0的演进历程。
很多同学觉得协议枯燥,觉得"我不做网络开发学这个没用"。其实不然,不管你是做后端、前端、客户端,甚至是测试、运维,只要你做的是和Web相关的开发,你每天都在和HTTP打交道。遇到跨域问题、缓存问题、性能问题、登录状态问题,追根溯源都是HTTP协议的问题。把HTTP搞懂了,很多问题自然就迎刃而解了。
希望这篇文章能帮大家真正理解HTTP协议,而不是停留在背面试题的层面。纸上得来终觉浅,绝知此事要躬行,赶紧打开编译器,自己写一个HTTP服务器试试吧!