【Linux】应用层协议—HTTP

一、HTTP协议介绍

  1. 请求-响应模型:HTTP (Hyper Text Transfer Protocol) 协议是基于请求和响应的。客户端(如Web浏览器)发送一个HTTP请求到服务器,服务器处理请求后返回一个HTTP响应。

  2. 无状态,无连接协议 :HTTP协议本身是无状态的,这意味着每个请求都是独立的,每次请求都需要建立新的连接。服务器不会保存任何关于前一个请求的信息。每次请求都需要包含所有必要的信息。

  3. HTTP 协议通常运行在 TCP 之上,即HTTP 是基于 TCP 实现的应用层协议。

  4. HTTP 协议定义了客户端 (如浏览器) 与服务器之间如何通信,用以交换或传输超文本。

    • 超文本:视频、音频、图片、图标、HTML 文件等。

二、URL URI URLN

  • URI: 统一资源标识符(Uniform Resource Identifier),用来标识资源的唯一性
  • URN: 统一资源名称(Uniform Resource Name),用名字标识资源
  • URL: 统一资源定位符(Uniform Resource Locator),给互联网上的每一个文件资源都贴上这样一个唯一标签,并且包含了资源位置信息和访问方式浏览器可以通过URL中的文件位置信息找到对应的资源文件。

平常所说的网址就是统一资源定位符 URL (Uniform Resource Lacator) 是因特网的万维网服务程序上用于指定信息位置的表示方法。

URL 的构成部分

  • 协议方案名: 发起请求用到的协议,http:// 表示在请求时需要使用的协议,通常使用的是 HTTP 或 HTTPS 协议。
  • 登录信息: 登录认证是用户的信息,有可能包含用户的用户名和密码。大多数的 URL 网址中,已经省略了该部分,转而将登录信息通过其他方案交付给服务器。
    • 例如验证码,扫码。
  • 服务器地址: 访问资源所在的服务器的地址,也就是域名(字符串风格的)。服务器地址 www.example.jp 也叫做域名。域名等价于 IP 地址, URL 中通过域名来映射对应服务器的 IP 地址
    • 浏览器会自动将域名转换成对应服务器的 IP 地址。
    • 可通过ping 域名 得到对应网站的ip

    如:

  • 端口号: 服务器绑定的端口号
  • HTTP 协议和套接字编程都是位于应用层,在进行套接字编程时需要给服务器绑定对应的 IP + port, HTTP 这个应用层协议也需要有明确的端口号。
  • 常见协议所对应的端口号
  • URL 一般会省略服务器端口号
    • 协议名称与端口号强关联,知名协议的端口号都是固定的。在使用某协议时,该协议实际就在为用户提供服务。
  • IP 地址和端口号缺一个都不可能访问到服务器。平时用的 URL 会省略服务器端口号,但在发起 HTTP 请求时,会自动拼接 80 这个端口号。
  • 发起其他协议请求时也会自动拼接与该协议所对应的端口号。
  • 文件路径: 访问资源在目标服务器上的位置信息
    • 带层次的文件路径 /dir/index.htm 表示的是要访问的资源的所在路径,也就是在该主机上唯一的文件资源
    • 从网络上获取资源本质上就是拷贝。从对应服务器中获取资源,并通过网络拿到自己手上。
  • 查询字符串: 查询信息
  • uid=1 表示的是请求服务时额外提供的参数,这些参数通常以键值对的形式呈现,通过 & 分隔。

栗子:在浏览器搜索关键词qq

  • 此处的 q=qq 就代表搜索关键词为qq
  • 片段标识符: 对某些资源信息的描述与补充
  • URL是URI的一种,URL是URI的一种具体表现,包含了资源的位置信息和获取资源的方式
  • URN是URI的一种,用特定命名字标识资源,但不包含访问方式。

三、urlencode和urldecode

1 .URL 对特殊字符的编码转义

  • 像 / ? : 等这样的字符, 已经被 url 当做特殊意义理解了. 因此这些字符不能随意出现.
    • 比如, 某个参数中需要带有这些特殊字符, 就必须先对特殊字符进行转义.

特殊字符的转义规则

  • 将需要转码的字符转为 16 进制,然后从右到左,取 4 位(不足 4 位直接处理),每 2 位做一位,前面加上%,编码成%XY 格式

例如:

  • "+" 被转义成了 "%2B"
  • 而urldecode 就是 urlencode 的逆过程;

2 .为什么要对特殊字符进行编码转义

  • 如果搜索的关键词包含特殊字符,不进行转义的话,这些特殊字符就可能会干扰到当前 URL,导致 URL 的链接出现问题。

3 .在线解码工具

在线解码工具在线解码工具

四、HTTP 协议的格式

1 .HTTP 协议的请求格式

  • 请求行:请求方法 + URL + HTTP 版本,这里的 URL 表示的是请求的资源的所在路径。
  • 请求报头:请求的属性,以key:value的形式显示,且用空行分隔每一个属性信息
  • 空行:分隔报头和报文,遇到空行就表示请求报头结束。
  • 请求正文:一般为用户的相关信息或数据,允许为空字符串,如果请求正文存在,则在请求报头中添加一个 content-length 属性来标识请求正文的长度。

问题:HTTP协议如何保证报头和有效载荷分离?

  • 当应用层收到一个 HTTP 请求时,需要将该 HTTP 请求的报头与有效载荷进行分离。
    • 对于一个 HTTP 请求,报头 = 请求行 + 请求报头;有效载荷 = 请求正文。
  • 可以根通过HTTP 请求中的空行来将报头和有效载荷分离。当服务器收到一个 HTTP 请求报文时,按行读取该报文,如果读取到空行则报头读取完毕。
  • 回车 + 换行 = \n,如果连续读取到两个 \n,则说明已将报头读取完毕,剩下的都是有效载荷。
  • 一般还会有Content-Length属性字段来标识正文的长度

问题:服务端如何保证自己读取报头完毕?

  • 循环读取,直到读到空行,就说明报头信息读取完毕

2 .HTTP****请求的代码

我们可以编写一个简单的基于TCP协议的服务器,并且通过以浏览器作为客户端,对服务器发起请求,并把请求部分打印下来,代码如下:

cpp 复制代码
#include <iostream>
#include <cstring>
#include <sys/socket.h>
#include <netinet/in.h>
#include <unistd.h>
#include <string>

#define PORT 8888

int main()
{
    int server_fd, new_socket;
    struct sockaddr_in address;
    int addrlen = sizeof(address);
    char buffer[1024] = {0};

    // 创建socket文件描述符
    if ((server_fd = socket(AF_INET, SOCK_STREAM, 0)) == 0)
    {
        perror("socket failed");
        exit(EXIT_FAILURE);
    }

    address.sin_family = AF_INET;
    address.sin_addr.s_addr = INADDR_ANY;
    address.sin_port = htons(PORT);

    // 绑定socket到端口8888
    if (bind(server_fd, (struct sockaddr *)&address, sizeof(address)) < 0)
    {
        perror("bind failed");
        exit(EXIT_FAILURE);
    }

    // 监听端口
    if (listen(server_fd, 3) < 0)
    {
        perror("listen");
        exit(EXIT_FAILURE);
    }

    std::cout << "Listening on port " << PORT << "..." << std::endl;

    // 接受连接
    if ((new_socket = accept(server_fd, (struct sockaddr *)&address, (socklen_t *)&addrlen)) < 0)
    {
        perror("accept");
        exit(EXIT_FAILURE);
    }

    // 读取请求
    read(new_socket, buffer, 1024);
    std::cout << buffer << std::endl;

    // 关闭socket
    close(new_socket);
    close(server_fd);

    return 0;
}

通过浏览器发送请求,结果如下:

请求行中 url 表示的是 web 根目录下的资源路径

  • 在请求报文的请求行中的 url 表示的是想要访问的资源的所在路径。
  • 而 url 当中的 / 不是云服务器上的根目录,而是 web 根目录。
  • 这个 web 根目录可以指定为你机器上的任何一个目录,不一定就非得是 Linux 的根目录。
  • http 会设置一个前缀路径表示 web 根目录,当接收到请求时,会将这个前缀路径和 url 所表示的资源路径拼接起来。这样就可以任意访问各种路径了
  • 在进行网页请求时,如果不指明请求的资源的所在路径,默认访问的是目标网站的首页,即 web 根目录下的 index.html 文件。
  • 在进行网页请求时,如果用户指明了请求的资源所在路径,就会直接到 web 根目录下访问指定资源。

3 . HTTP 协议的响应格式

  • 状态行:HTTP 版本 + 状态码 + 状态码描述。
  • 响应报头:响应的属性,这些属性都以 key: value 的形式按行陈列。
  • 空行:遇到空行就表示响应报头结束。
  • 响应正文:这里面存着请求的资源,一般为 html、图片、音频等内容。如果响应正文存在,则在响应报头中添加一个 content-length 属性来标识响应正文的长度。

将 HTTP 响应报文的报头和有效载荷分离

  • 对于一个 HTTP 响应报文来说,报头 = 状态行 + 响应报头;有效载荷 = 响应正文。
  • 分离方式与 HTTP 请求相同,客户端按行读取获取的响应报头,如果读取到空行则说名报头读取完毕。
  • 从代码层面上看,连续读取到两个 \n 就表示报头读取完毕。

4 . HTTP响应代码

  • 为了更好地看到响应的效果,这里再上面的代码的基础上增加一点响应的部分,其中包含两个字段:Content-Type(正文格式,数据类型)Content-Length(正文长度) 两个字段

这里我们正文返回一个html格式的表单,具体如下:

cpp 复制代码
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>注册页面</title>
</head>
	<body>
	    <!-- 表单域 form 表单域action url 地址 method 提交方式 name 表单名称-->
	    <form method = "POST" name="注册表" action="mysql_cgi">
	        <!-- input type 属性值 -->
	        <!-- text 正常显示 password  -->
	        用户名:<input type="text" name = "username"> <br/>
	        密码:<input type="password" name = "password"> <br/>
	        <input type=submit value="注册"> 
	    </form>
	</body>
</html>
  • 这里使用sendfile这个接口来发送该文本,该接口可以直接将一个文件的内容拷贝给另一个文件,且在内核中完成该操作,效率极高,

介绍:

  • sendfile 是一个在 Linux 内核中提供的系统调用,用于高效地将文件内容发送到套接字。
  • 这个系统调用特别适用于需要将文件内容传输到网络上的场景,比如Web服务器传输静态文件时。
  • sendfile 的优势在于它可以直接在内核空间将数据从一个文件描述符传输到另一个文件描述符,避免了数据在内核空间和用户空间之间的复制,从而提高了数据传输的效率。

函数原型:

cpp 复制代码
#include <sys/sendfile.h>

ssize_t sendfile(int out_fd, int in_fd, off_t *offset, size_t count);
  • out_fd:输出文件描述符,即套接字。
  • in_fd:输入文件描述符,即要发送的文件。
  • offset:一个指向 off_t 类型的指针,用于指定从文件的哪个位置开始发送数据。如果传递 NULL,则从当前文件偏移量开始发送。
  • count:要发送的数据量。

返回值

  • 成功时,返回实际发送的字节数。
  • 失败时,返回 -1 并设置 errno 以指示错误。
  • sendfile这个接口中,需要填充需要发送多少字节,这里我们发送整个文件,所以这里为了能够获取一个文件大小,这里再介绍一个接口stat。

介绍如下:

函数原型

cpp 复制代码
#include <sys/types.h>
#include <sys/stat.h>
#include <unistd.h>

int stat(const char *path, struct stat *buf);
  • path:指向文件路径的指针。
  • buf:指向 stat 结构体的指针,该结构体用于存储文件的状态信息。

stat 结构体

stat 结构体包含了文件的各种属性,其定义如下:

cpp 复制代码
struct stat {
    dev_t     st_dev;     /* ID of device containing file */
    ino_t     st_ino;     /* inode number */
    mode_t    st_mode;    /* protection */
    nlink_t   st_nlink;   /* number of hard links */
    uid_t     st_uid;     /* user ID of owner */
    gid_t     st_gid;     /* group ID of owner */
    off_t     st_size;    /* total size, in bytes */
    blksize_t st_blksize; /* blocksize for filesystem I/O */
    blkcnt_t  st_blocks;  /* number of 512B blocks allocated */
    time_t    st_atime;   /* time of last access */
    time_t    st_mtime;   /* time of last modification */
    time_t    st_ctime;   /* time of last status change */
};

响应代码:

cpp 复制代码
#include <iostream>
#include <cstring>
#include <sys/socket.h>
#include <netinet/in.h>
#include <unistd.h>
#include <string>
#include <fcntl.h>
 #include <sys/stat.h>
 #include <sys/sendfile.h>

#define PORT 8888

int main()
{
    int server_fd, new_socket;
    struct sockaddr_in address;
    int addrlen = sizeof(address);
    char buffer[1024] = {0};

    // 创建socket文件描述符
    if ((server_fd = socket(AF_INET, SOCK_STREAM, 0)) == 0)
    {
        perror("socket failed");
        exit(EXIT_FAILURE);
    }

    address.sin_family = AF_INET;
    address.sin_addr.s_addr = INADDR_ANY;
    address.sin_port = htons(PORT);

    // 绑定socket到端口8888
    if (bind(server_fd, (struct sockaddr *)&address, sizeof(address)) < 0)
    {
        perror("bind failed");
        exit(EXIT_FAILURE);
    }

    // 监听端口
    if (listen(server_fd, 3) < 0)
    {
        perror("listen");
        exit(EXIT_FAILURE);
    }

    std::cout << "Listening on port " << PORT << "..." << std::endl;

    // 接受连接
    if ((new_socket = accept(server_fd, (struct sockaddr *)&address, (socklen_t *)&addrlen)) < 0)
    {
        perror("accept");
        exit(EXIT_FAILURE);
    }

    // 读取请求
    read(new_socket, buffer, 1024);
    std::cout << "Client request: " << buffer << std::endl;

    // 响应
    int fd = open("index1.html", O_RDONLY);
    struct stat st;
    stat("./index1.html", &st);

    std::string status_line = "HTTP/1.1 200 OK\n";
    // 2.响应报头
    std::string response_header = "Content-Length: " + std::to_string(st.st_size) + "\n";
    response_header += "Content-Type: text/html\n";
    //  3.空行
    std::string blank = "\n";
    // 4.正文

    send(new_socket, status_line.c_str(), status_line.size(), 0);
    send(new_socket, response_header.c_str(), response_header.size(), 0);
    send(new_socket, blank.c_str(), blank.size(), 0);

    sendfile(new_socket, fd, nullptr, st.st_size);
    close(fd);

    // 关闭socket
    close(new_socket);
    close(server_fd);

    return 0;
}

浏览器访问结果:

用telnet做测试:

  • 另外还可以用postman之类的工具做测试。

五、HTTP常见的请求方法

列举常见的几种:

  • 说明: HTTP/1.1在HTTP/1.0基础上增加了长连接和缓存处理等内容,HTTP/1.0是基于请求与响应的,每次发送请求都需要重新建立连接,获得响应后关闭连接,而HTTP/1.1是支持长连接,客户端可以通过一个连接向服务器发起多个HTTP请求,上层依次读取请求后还会保持连接。
  • 在 HTTP 的请求应用中,99% 用的都是 GET 和 POST 方法,而在这 99% 中,GET 方法又占到了 80%。
  • 网络中的行为总共就两种:上传和下载。
    • GET 可以直接获取资源,还可以上传数据,通过url进行参数的传递(例如:?a=10&b=20)

    • POST 上传数据。通过正文进行传参,报头中还会携带Content-Length字段,说明正文内容大小

1 .GET 方法(重要)

  • 用途:向服务器发送 GET 请求,用于从服务器中获取数据 (下载)。
    • GET 请求方法通过 URL 传参。客户端向服务端获取请求行中 URL 所指定的资源。
  • 栗子:GET /index.html HTTP/1.1,获取根目录下 index.html 文件的内容。
  • 特性:指定要访问的资源会在经过服务器端的解析后再返回响应内容。

2 .POST 方法(重要)

  • 用途:向服务器发送 POST 请求,用于往服务器中传输数据 (上传)。
    • POST 请求方法通过正文传参。将请求正文中的数据传输给服务器,通常用于提交表单数据。
  • 示例:POST /submit.cgi HTTP/1.1,将 submit.cgi 中的数据发送给服务器。
  • 特性:可以发送大量的数据给服务器,并且数据包含在请求正文中。

3 . PUT 方法 (少用)

  • 用途:向服务器传输文件,将请求报文中主体中的文件保存到请求行的 URL 所指定的位置。
    • 但是向服务器随意上传文件的行为是被 HTTP 禁止的。
  • 示例:PUT /example.html HTTP/1.1,向服务器上传 example.html 文件。
  • 特性:不太常用,但在如 RESTful API 等情况下,用于更新资源。

4 . HEAD 方法

  • 用途:与 GET 方法类似,但不返回报文主体部分,仅返回响应头。
  • 示例:HEAD /index.html HTTP/1.1
  • 特性:用于确认 URL 的有效性及资源更新的日期时间等。

5 .DELETE 方法 (少用)

  • 用途:删除服务器上的文件,和 PUT 方法的功能相反,将请求行中的 URL 所指定的文件删除。
    • 但是,随意删除服务器上的文件的行为是被 HTTP 禁止的。
  • 示例:DELETE /example.html HTTP/1.1,删除服务器上的 example.html 文件。
  • 特性:删除请求行中的 URL 所指定的资源。

6 .OPTIONS 方法

  • 用途:查询针对请求行中的 URL 所指定的资源支持的方法。
  • 示例:OPTIONS * HTTP/1.1
  • 特性:返回被允许的方法,如 GET、POST 等。

六、HTTP 的状态码

1 .状态码的分类

  • 根据开头的数字将 HTTP 的状态码划分成 5 大类,HTTP 的状态码分类如下:

2 .HTTP 常见状态码

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

3 . Redirection 重定向状态码

  • 重定向是通过各种方法将网络请求重新定个方向转到其他位置,此时的这个服务器提供的服务相当于是引路。
    • 例:手机上APP的 摇一摇广告,刚打开软件一不小心摇了一下手机就给我重定向到淘宝。
  • 引路:客户端向 A 服务器发送 http 请求后,A 服务器返回给客户端的响应报文中,响应正文不会携带任何内容。而是会在响应报文中添加一个 Location 报头,告知客户端应该去访问指定的网站,此时客户端就会向指定网站的服务器 B 发送 http 请求报文,由服务器 B 为客户端提供服务。

重定向分类

HTTP状态码301**(永久重定向)**:

  • 当服务器返回 HTTP 301 状态码时,表示请求的资源已经被永久移动到新的位置。

  • 在这种情况下,服务器会在响应中添加一个 Location 头部,用于指定资源的新位置。这个 Location 头部包含了新的 URL 地址,浏览器会自动重定向到该地址。

    • 例如,在 HTTP 响应中,可能会看到类似于以下的头部信息:
    cpp 复制代码
    HTTP/1.1 301 Moved Permanently\r\n
    Location: https://www.new-url.com\r\n

HTTP状态码302**(临时重定向)**:

  • 当服务器返回 HTTP 302 状态码时,表示请求的资源临时被移动到新的位置。

  • 同样地,服务器也会在响应中添加一个 Location 头部来指定资源的新位置。浏览器会暂时使用新的 URL 进行后续的请求,但不会缓存这个重定向。

    • 例如,在 HTTP 响应中,可能会看到类似于以下的头部信息:
    cpp 复制代码
    HTTP/1.1 302 Found\r\n
    Location: https://www.new-url.com\r\n

总结

  • 无论是 HTTP 301 还是 HTTP 302 重定向,都需要依赖 Location 选项来指定资 源的新位置。这个 Location 选项是一个标准的 HTTP 响应头部,用于告诉浏览器应该 将请求重定向到哪个新的 URL 地址。

七、HTTP 的常见报头

1 .Host 报头

  • Host 报头中存储着的是客户端真正想要访问的服务所在的 IP 地址和端口号。
    • 当使用浏览器访问某个服务器时,浏览器发送的 HTTP 请求 Host 中填的就是该服务器的 IP 和端口号。
  • 由于有些服务器实际提供的是代理服务 (代替客户端向其他服务器发起请求),要访问的文件资源可能并不在当前服务器上。
    • 所以 Host 中存着的才是真正的提供服务的服务端。
  • 代理服务器要执行代理功能,首先得知道客户端要访问得资源在哪里,然后再将响应报文返回给客户端。
    • 例:如果启动了 fiddler 这个软件,浏览器发起的 http 请求就会被这个软件抓包,该软件执行的就是代理服务。
    • 该软件会代替客户端将请求报文发送给 Host 所指定的服务器,服务器就认为是该软件给它发送的请求,于是会将响应报文返回给该软件,最后该软件将响应报文发送给客户端。
    • 这也就是所谓的科学上网

2 .User-Agent 报头

  • User-Agent 报头中存储着发送请求的客户端所对应的操作系统和浏览器的版本信息。

3 . Referer 报头

  • Referer 记录着当前是从哪一个页面跳转过来的,方便回退到上一个页面。
  • 用于在客户端中存储少量信息,通常用于实现会话 (Session) 功能。
  • HTTP 是一种无状态,无连接的协议,并不会保存客户端的信息。但在实际场景中,大部分网站都会记住你的登录信息,这就是通过 Cookie 实现的。

查看网站的Cookie

  • Cookie 用于在客户端中存储少量的信息,由于 HTTP 是一种无状态的协议 (服务器不会保存客户端的信息),如果没有 Cookie,每次页面请求时都需要重新认证用户信息。
    • 例:看 VIP 视频时,每个视频都是一个新的 HTTP 请求,如果每一集都要客户端进行 VIP 认证,这样就很麻烦。
  • HTTP 中有一个报头是 Set-Cookie,可以用来给浏览器设置 Cookie 值。
  • 当第一次登录某个网站时,需要进行用户认证。此时如果服务器在经过数据对比之后判断为合法用户,就会进行 Set-Cookie 的设置,填充用户登录信息。
  • 当认证通过并在给返回客户端的http中设置了 Set-Cookie 报头后,服务器返回给浏览器的 HTTP 响应报文就会携带上 Cookie 报头及其对应的值。
  • 客户端在收到响应报文之后,会提取出 Set-Cookie 报头中的值,并将其保存在浏览器的 Cookie 文件中,此时就将认证信息保存在本地客户端的 Cookie 文件了。
  • 往后 HTTP 发送的任何信息,都会携带上 Cookie 文件中的内容,不需要用户自己进行认证。
    对应网站的各种 Cookie 数据。
  • 看到的这些 Cookie 数据都是由对应的服务器方写的,将某些包含登陆时所设置信息的 Cookie 数据删除的话就可能会导致需要重新进行登录认证。
  • 一般Cookie也会有时间限制,超过一定时间该Cookie就会失效,需要再次认证添加新的Cookie

5 .connection****报头

  • HTTP 中的 Connection 字段是 HTTP 报文头的一部分,它主要用于控制和管理客户端与服务器之间的连接状态

核心作用

  • 管理持久连接:Connection 字段还用于管理持久连接(也称为长连接)。持久连接允许客户端和服务器在请求/响应完成后不立即关闭 TCP 连接,以便在同一个连接上发送多个请求和接收多个响应。

持久连接(长连接)

  • 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 连接。

八、HTTP****历史及版本核心技术与时代背景

  • HTTP(Hypertext Transfer Protocol,超文本传输协议)作为互联网中浏览器和服务器间通信的基石,经历了从简单到复杂、从单一到多样的发展过程。以下将按照时间顺序,介绍 HTTP 的主要版本、核心技术及其对应的时代背景。

1 .HTTP/0.9

核心技术:

  • 仅支持 GET 请求方法
  • 仅支持纯文本传输,主要是 HTML 格式
  • 无请求和响应头信息。

时代背景

  • 1991 年,HTTP/0.9 版本作为 HTTP 协议的最初版本,用于传输基本的超文本
  • HTML 内容。
  • 当时的互联网还处于起步阶段,网页内容相对简单,主要以文本为主。

2 .HTTP/1.0

核心技术

  • 引入 POST 和 HEAD 请求方法。
  • 请求和响应头信息,支持多种数据格式(MIME)。
  • 支持缓存(cache)。
  • 状态码(status code)、多字符集支持等。

时代背景

  • 1996 年,随着互联网的快速发展,网页内容逐渐丰富,HTTP/1.0 版本应运而生。
  • 为了满足日益增长的网络应用需求,HTTP/1.0 增加了更多的功能和灵活性。
  • 然而,HTTP/1.0 的工作方式是每次 TCP 连接只能发送一个请求,性能上存在一定局限

3 .HTTP/1.1

核心技术

  • 引入持久连接(persistent connection),支持管道化(pipelining)。
  • 允许在单个 TCP 连接上进行多个请求和响应,提高了性能。
  • 引入分块传输编码(chunked transfer encoding)。
  • 支持 Host 头,允许在一个 IP 地址上部署多个 Web 站点。

时代背景

  • 1999 年,随着网页加载的外部资源越来越多,HTTP/1.0 的性能问题愈发突出。
  • HTTP/1.1 通过引入持久连接和管道化等技术,有效提高了数据传输效率。
  • 同时,互联网应用开始呈现出多元化、复杂化的趋势,HTTP/1.1 的出现满足了这些需求。

4 . HTTP/2.0

核心技术

  • 多路复用(multiplexing),一个 TCP 连接允许多个 HTTP 请求。
  • 二进制帧格式(binary framing),优化数据传输。
  • 头部压缩(header compression),减少传输开销。
  • 服务器推送(server push),提前发送资源到客户端。

时代背景

  • 2015 年,随着移动互联网的兴起和云计算技术的发展,网络应用对性能的要求越来越高。
  • HTTP/2.0 通过多路复用、二进制帧格式等技术,显著提高了数据传输效率和网络性能。
  • 同时,HTTP/2.0 还支持加密传输(HTTPS),提高了数据传输的安全性。

5 .HTTP/3.0

核心技术

  • 使用 QUIC 协议替代 TCP 协议,基于 UDP 构建的多路复用传输协议。
  • 减少了 TCP 三次握手及 TLS 握手时间,提高了连接建立速度。
  • 解决了 TCP 中的线头阻塞问题,提高了数据传输效率。

时代背景

  • 2022 年,随着 5G、物联网等技术的快速发展,网络应用对实时性、可靠性的要求越来越高。
  • HTTP/3.0 通过使用 QUIC 协议,提高了连接建立速度和数据传输效率,满足了这些需求。
  • 同时,HTTP/3.0 还支持加密传输(HTTPS),保证了数据传输的安全性。
相关推荐
奥利奥夹心脆芙42 分钟前
辅助排查 HTTP 接口代码报错,实操完整案例分享
http
Misnearch43 分钟前
抓包Packet Capture
网络·抓包
zhangfeng11331 小时前
ps aux讲解,结合国家超算中心 hpc apptainer
linux·服务器·网络
吠品2 小时前
一次 Nginx 报错 unexpected end of file 的排查记录
网络协议·https·ssl
代码中介商2 小时前
TLS握手全解析:从1.2到1.3的加密演进
网络·网络协议·http
xlq223222 小时前
66.ip
网络·网络协议·tcp/ip
tudoSearcher2 小时前
手机、平板、电脑同时控制Claude Code / Codex ?:Paseo实战指南
网络·开源·开源软件·个人开发·ai编程
加农炮手Jinx2 小时前
Flutter for OpenHarmony:pub_updater 命令行工具自动更新专家(DevOps 运维必备) 深度解析与鸿蒙适配指南
android·运维·网络·flutter·华为·harmonyos·devops
华纳云IDC服务商2 小时前
高防CDN和高防IP一起用,延迟会增加多少?
网络·网络协议·tcp/ip
sxd20013 小时前
Debian #1135514 bug引发的思考
网络·debian·bug