HTTP协议简介

Web 是互联网上最流行的应用,没有之一。Web 网站由 HTML 网页和相关资源组成,通过 Web 服务器对外服务。用户则通过浏览器连接 Web 服务器,浏览网页。

世界上有成千上万的网站,而浏览器也是五花八门。浏览器 和 Web 服务器必须对如何请求和响应数据达成一致,否则就乱套了。这就是本文要讨论的 超文本传输协议hypertext transfer protocol ),即 HTTP 协议负责的范畴。

HTTP 协议是一种应用层协议,它规定了参与 Web 通信的浏览器和 Web 服务器之间的通信细节。HTTP 协议主要用于传输超文本网页及其相关网络资源,其中

  • Web 浏览器browser )作为客户端,主动发起 请求request );
  • Web 服务器server )作为服务端,被动回复 响应response );

依赖TCP

无论是 Web 服务器还是浏览器,一般都是由进程运行。我们知道,进程间的网络通信是由传输层协议负责的,这跟 HTTP 协议有什么关系呢?为什么还需要 HTTP 协议呢?

其实,传输层协议和应用层并不冲突,后者是在前者基础上的发展和补充。传输层让进程具备互发数据的能力,但对具体的数据格式并不关心。而数据格式显然跟具体应用相关,Web 应用跟电子邮件肯定不同,由应用层来定义更为合适。

HTTP 协议有赖于 TCP 协议提供的传输层信道,Web 服务器以 80 为默认端口。

浏览器请求资源时,先建立到服务器的 TCP 连接,再通过 TCP 提供的字节流传输服务发送 请求 。服务器收到请求后,同样通过 TCP 提供的字节流服务回复 响应 。至于请求和响应的具体格式,则由 HTTP 协议定义。

  • TCP 提供字节流传输服务;
  • HTTP 规定了请求和响应的格式;

连接建立

那么,HTTP 规定的请求和响应的格式大概是怎样的呢?接下来,以小菜的个人简介为例,学习 HTTP 协议的格式和通信过程。网页 URL 是:http://cors.fasionchan.com/about.html

当浏览器访问这个 URL 时,它根据 URL 格式解析出服务器主机部分 cors.fasionchan.com 。这是一个域名,必须先通过 DNS 解析为 IP 地址后,方能连接。

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
root@netbox [ ~ ]  ➜ dig cors.fasionchan.com

; <<>> DiG 9.16.1-Ubuntu <<>> cors.fasionchan.com
;; global options: +cmd
;; Got answer:
;; ->>HEADER<<- opcode: QUERY, status: NOERROR, id: 11185
;; flags: qr rd ra; QUERY: 1, ANSWER: 2, AUTHORITY: 0, ADDITIONAL: 0

;; QUESTION SECTION:
;cors.fasionchan.com.		IN	A

;; ANSWER SECTION:
cors.fasionchan.com.	15	IN	CNAME	cors.fasionchan.com.w.cdngslb.com.
cors.fasionchan.com.w.cdngslb.com. 15 IN A	124.227.151.227

;; Query time: 15 msec
;; SERVER: 192.168.65.1#53(192.168.65.1)
;; WHEN: Mon Feb 14 15:11:08 CST 2022
;; MSG SIZE  rcvd: 97

得到目标 Web 服务器的 IP 地址后,浏览器便可建立到服务器 80 端口的 TCP 连接。

HTTP请求

TCP 连接建好后,浏览器便可组织 HTTP 请求,并通过 TCP 连接发给服务器,格式如下:

1
2
3
4
5
GET /about.html HTTP/1.1
Host: cors.fasionchan.com
User-Agent: curl/7.64.1
Accept: */*

可以看到 HTTP 请求由一些文本行构成,每一行以 \r\n 换行,分为几个部分:

  • 请求行line ),位于第一行,描述想要请求的资源和协议版本;
  • 请求头header )可选,位于请求行之后,一个一行,可能有若干行;
  • 空行
  • 请求体body ),位于空行之后,可选;

请求行

请求行分为 3 部分,以空格分隔,依次是:

  • 请求方法method ),GET 方法表示获取;
  • 请求路径path ),即待请求的资源在服务器上的路径,通常是 URL 上的路径部分;
  • 协议版本version ),例子使用的是 HTTP 协议 1.1 版本;

请求方法

HTTP 支持多种请求方法,各代表不同的请求语义,大致罗列如下表:

请求方法 语义 说明
GET 获取 获取资源数据
POST 提交 提交数据给服务器,比如提交表单
PUT 替换 更新指定资源,更新策略为整体替换
PATCH 部分更新 更新指定资源,更新策略为部分更新
DELETE 删除 删除指定资源

请求头

HTTP 请求头位于请求行后,由若干字段组成,每个字段占一行。每一行包含字段名和对应的值,中间以英文冒号 : 隔开。通过 HTTP 请求头,客户端可以将一些元信息告诉服务器。

举个例子, User-Agent 将客户端的具体类型告诉服务器;而 Host 头部则告诉服务器客户端想要访问的站点,一般为 URL 中的服务器主机部分。一台 Web 服务器能够同时服务多个站点,Host 头指定了请求的目标站点。

HTTP响应

Web 服务器接到 HTTP 请求后,解析协议便知道客户端想要的资源。它取出资源后,组织 HTTP 响应,并通过 TCP 连接回复客户端,格式如下:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
HTTP/1.1 200 OK
Server: Tengine
Content-Type: text/html
Content-Length: 1392

<!DOCTYPE html>
<html>
  <head>
    <meta charset="utf-8">
    <title>关于小菜</title>
    <link href="./about-style.css" rel="stylesheet" />
  </head>
  <body>
    <section class="intro">
      <h1>关于小菜</h1>
      <img src="https://fasionchan.com/images/profile.png" class="avatar"/>
      <!-- 此处有省略 -->
  </body>
</html>

HTTP 响应跟 HTTP 请求非常类似,同样由一些文本行构成,分为几个部分:

  • 状态行status line ),位于第一行,表示请求的结果是否成功;
  • 响应头header ),跟请求头类似;
  • 空行
  • 响应体body ),即服务器返回的资源内容;

状态行

状态行同样分为 3 部分,以空格分隔,依次是:

  • 协议版本version );
  • 状态码status code ),描述请求状态,200 表示成功;
  • 原因措词reason phrase ),状态码的可读说明,可为空;

状态码

状态码由 3 位数字组成,描述请求状态,根据数字第 1 位可分为 5 类:

类别 语义 说明
1XX 提示
2XX 成功
3XX 重定向
4XX 客户端错误
5XX 服务端错误

例子中服务器返回的状态码是 200 ,表示请求成功。

响应头

响应头跟请求头类似,同样由若干字段组成,每个字段占一行。

例子中的服务器,通过 Content-Type 响应头告知客户端资源的类型是 text/html ,也就是 HTML 网页;Content-Length 头则告诉客户端资源大小是 1392 字节。

HTTP头部

由于头部字段请求和响应都有,因而经常统称为 HTTP 头部header )。HTTP 头部分为很多字段,有些字段是请求和响应通用的,有些是请求或响应特有的:

  • 通用头字段general ),请求和响应都支持的字段;
  • 请求头字段request ),请求特有的字段;
  • 响应头字段response )响应特有的字段;
  • 实体头字段entity ),实体相关字段;

响应体

响应头之后跟着一个空行,然后就是响应体,它保存着资源本身。回到上面例子,我们可以看到响应体中保存的 HTML 网页内容,即网页的源代码。

顺便提一句,浏览器根据 Content-Length 头标注的字节数读取整个响应体,然后根据 Content-Type 头标注的类型对数据进行处理。对于 HTML 网页,浏览器将其解析成 DOM 结构并渲染出来。

小结

HTTP 协议位于应用层,是 Web 应用的核心协议,负责超文本网页和相关数据资源的传输。浏览器作为客户端主动发起 HTTP 请求,而 Web 服务器作为服务端被动回复 HTTP 响应。

HTTP 协议是基于文本的网络协议,请求和响应均由一些文本行构成。

HTTP 请求分为 3 部分:

  • 请求行,以空格为分隔符分为 3 部分:
    • 请求方法
    • 请求路径
    • 协议版本
  • 请求头
  • 请求体

HTTP 响应分为 3 部分:

  • 状态行,以空格为分隔符分为 3 部分:
    • 协议版本
    • 状态码
    • 原因措词
  • 响应头
  • 响应体

小菜学网络】系列文章首发于公众号【小菜学编程】,敬请关注:

【小菜学网络】系列文章首发于公众号【小菜学编程】,敬请关注: