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 地址后,方能连接。
|
|
得到目标 Web 服务器的 IP 地址后,浏览器便可建立到服务器 80 端口的 TCP 连接。
HTTP请求
TCP 连接建好后,浏览器便可组织 HTTP 请求,并通过 TCP 连接发给服务器,格式如下:
|
|
可以看到 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 连接回复客户端,格式如下:
|
|
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 部分:
- 协议版本
- 状态码
- 原因措词
- 响应头
- 响应体
【小菜学网络】系列文章首发于公众号【小菜学编程】,敬请关注: