(在本文中我将解释 HTTP/1.1,但现在主要用的是 HTTP/2。我在本文中也会介绍!)
一旦建立了 TCP 连接,我们就可以向服务器发送数据以及从服务器接收数据。我们可以用 HTTP 请求,询问服务器是否可以提供我们所需的数据。然后服务器用 HTTP 响应进行应答。在这个步骤中,我们将最终得到如下流程:
HTTP 请求
典型的 HTTP 请求只是纯文本,至少又如下两部分组成:
请求行。我们要从服务器获取哪些数据,以及使用的是哪个 HTTP 版本?
请求头。为服务器提供额外的信息,比如我们将接受那种类型的数据,或者如果数据已经缓存在某个地方,就告诉服务器不要将数据返回给我们。
请求行由三个部分组成:HTTP 方法、资源定位、协议版本。
HTTP 方法有好几种,不过最常用的是:
- GET:从资源获取数据(喂,我能得到位于我指定的资源位置的数据(在本例中是 /index.html)吗?)
- POST:发送新数据给资源(喂,这里有全新的数据可以添加到资源位置 /index.html!)
- PUT:用正在发送的数据替换资源上已有的数据(我知道你在资源位置/index.html上已经有了数据,但这里有其他数据,你应该用这些数据替换所有旧数据)
- DELETE: 删除资源(我不再需要 /index.html,请删除它)
请求头是一组字段/值对。有很多可选的请求头,但两个必需的是 Host 和 Connection。
Host:我们要面向的域名。在本例中是 www.google.com。
Connection:通常,这个值要么是
keep-alive
,要么是close
,表示客户端和服务器之间的连接(即TCP连接)应该保持打开还是关闭。通常,对于每个 HTTP 请求,都会打开一个新的 TCP 连接。如果用keep-alive
,就是连续的 HTTP 连接。
典型的 HTTP 请求如下所示:
1 | GET /index.html |
HTTP 响应
服务器接受和处理 HTTP 请求。基于请求,生成 HTTP 响应。典型的 HTTP 响应由如下部分组成:
- 状态行。显示请求是否被成功处理,如果没有,就让我们知道到底哪里出错了。
- 响应头。跟请求头一样,响应头给我们提供有关响应的更多信息。它是什么时候请求的?它请求的是什么类型的数据?数据有多少个字节?生成此响应的服务器是什么类型的?
- 响应体。如果请求成功了,响应体就包含了我们所请求的资源。
状态行由协议版本(本例中是 HTTTP/1.1)和状态码组成。状态码的值向我们展示请求是如何被处理的:是成功了,还是有错误?
常见的状态码为:
200 OK
:一切都很好,请求成功了!400 Bad Request
:发送到服务器的 HTTP 请求的语法无效。401 Unauthorized
:试图请求未经授权的资源。403 Forbidden
:需要更多权限才能访问此资源。404 Not Found
:服务器找不到要的资源。500 Internal Server Error
:由于某种原因,服务器端发生了错误。原因可能有很多种,但是服务器因此无法处理用户请求了。
所有以 2xx
开头的状态码都表示成功,以 4xx
开头的表示客户端错误,而以 5xx
开头的表示服务器端错误。
响应头与请求头一样,是一组包含有关响应信息的键/值对。报头类型很多,但常见的有:
Date
:资源是什么时候被请求的?Server
:从哪种类型的服务器请求资源?Content-Type
:请求的内容是什么类型的数据?这显示为 MIME(Multipurpose Internet Mail Extensions,多用途互联网邮件扩展)类型。Content-Length
:响应体中的数据有多少字节?
基于文件内容的一些常见的 MIME 类型包括:
典型的响应就是这样子的:
1 | 200 OK |
或者,把每个单独的部分可视化一下:
在响应体中,我们最终得到了我们请求的资源!既然客户端已经得到了请求的数据(在本例中是 HTML),那么我们最终就可以启动在屏幕上显示它们的过程了。