HTTP 建立连接-发起请求-服务器响应过程详解

128 阅读5分钟

携手创作,共同成长!这是我参与「掘金日新计划 · 8 月更文挑战」的第8天,点击查看活动详情

典型的 HTTP 会话

在客户端-服务器协议(如 HTTP)中,会话由三个阶段组成:

  1. 客户端建立 TCP 连接(如果传输层不是 TCP,则建立相应的连接)。
  2. 客户端发送其请求,并等待答案。
  3. 服务器处理请求,发回其答案,提供状态代码和适当的数据。

从 HTTP/1.1 开始,连接在完成第三阶段后不再关闭,客户端现在被授予进一步的请求:这意味着第二阶段和第三阶段现在可以执行任意次数。

建立连接

在客户端-服务器协议中,是客户端建立连接。在 HTTP 中打开连接意味着在底层传输层(通常是 TCP)中启动连接。

对于 TCP,计算机上的 HTTP 服务器的默认端口是端口 80。也可以使用其他端口,如 8000 或 8080。要获取的页面的URL包含域名和端口号,但如果端口号为80,则可以省略后者。有关更多详细信息,请参阅在 Web 上标识资源。

注意: 客户端-服务器模型不允许服务器在没有显式请求的情况下向客户端发送数据。为了解决这个问题,Web开发人员使用几种技术:通过XMLHTTPRequestfetch()API,使用WebSockets API或类似协议定期ping服务器。

发送客户端请求

建立连接后,用户代理可以发送请求(用户代理通常是Web浏览器,但可以是其他任何东西,例如爬虫)。客户端请求由文本指令组成,由 CRLF(回车符,后跟换行符)分隔,分为三个块:

  1. 第一行包含一个请求方法,后跟其参数:

    • 文档的路径,作为没有协议或域名的绝对URL
    • HTTP 协议版本
  2. 后续行表示 HTTP 标头,为服务器提供有关哪种类型的数据是合适的(例如,哪种语言、什么 MIME 类型)或其他更改其行为的数据(例如,如果答案已缓存,则不发送答案)的信息。这些 HTTP 标头形成一个以空行结尾的块。

  3. 最后一个块是可选的数据块,它可能包含主要由POST方法使用的进一步数据。

示例请求

获取 developer.mozilla.org () 的根页面,并告诉服务器用户代理更喜欢法语页面,如果可能的话:https://developer.mozilla.org/

GET / HTTP/1.1
Host: developer.mozilla.org
Accept-Language: fr

观察最后一个空行,这会将数据块与标头块分开。由于 HTTP 标头中没有提供,因此此数据块显示为空,标记标头的末尾,允许服务器在收到此空行时处理请求。

例如,发送表单的结果:

POST /contact_form.php HTTP/1.1
Host: developer.mozilla.org
Content-Length: 64
Content-Type: application/x-www-form-urlencoded

name=Joe%20User&request=Send%20me%20one%20of%20your%20catalogue

请求方法

HTTP 定义了一组请求方法,指示要对资源执行的所需操作。虽然它们也可以是名词,但这些请求方法有时被称为 HTTP 谓词。最常见的请求是 和 :GET``POST

  • GET 方法请求指定资源的数据表示形式。使用 的请求应仅检索数据。GET
  • POST 方法将数据发送到服务器,以便它可以更改其状态。这是通常用于 HTML 表单的方法。

服务器响应的结构

在连接的代理发送其请求后,Web 服务器将处理该请求,并最终返回响应。与客户端请求类似,服务器响应由文本指令组成,由CRLF分隔,但分为三个块:

  1. 第一行,即状态行,包括对所用 HTTP 版本的确认,后跟响应状态代码(及其在人类可读文本中的简短含义)。
  2. 后续行表示特定的 HTTP 标头,为客户端提供有关发送的数据的信息(例如,类型、数据大小、使用的压缩算法、有关缓存的提示)。与客户端请求的 HTTP 标头块类似,这些 HTTP 标头形成以空行结尾的块。
  3. 最后一个块是数据块,其中包含可选数据。

示例响应

成功的网页响应:

HTTP/1.1 200 OK
Content-Type: text/html; charset=utf-8
Content-Length: 55743
Connection: keep-alive
Cache-Control: s-maxage=300, public, max-age=0
Content-Language: en-US
Date: Thu, 06 Dec 2018 17:37:18 GMT
ETag: "2e77ad1dc6ab0b53a2996dfd4653c1c3"
Server: meinheld/0.6.1
Strict-Transport-Security: max-age=63072000
X-Content-Type-Options: nosniff
X-Frame-Options: DENY
X-XSS-Protection: 1; mode=block
Vary: Accept-Encoding,Cookie
Age: 7

<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="utf-8">
  <title>A simple webpage</title>
</head>
<body>
  <h1>Simple HTML5 webpage</h1>
  <p>Hello, world!</p>
</body>
</html>

请求的资源已永久移动的通知:

HTTP/1.1 301 Moved Permanently
Server: Apache/2.4.37 (Red Hat)
Content-Type: text/html; charset=utf-8
Date: Thu, 06 Dec 2018 17:33:08 GMT
Location: https://developer.mozilla.org/ (this is the new link to the resource; it is expected that the user-agent will fetch it)
Keep-Alive: timeout=15, max=98
Accept-Ranges: bytes
Via: Moz-Cache-zlb05
Connection: Keep-Alive
Content-Length: 325 (the content contains a default page to display if the user-agent is not able to follow the link)

<!DOCTYPE html>… (contains a site-customized page helping the user to find the missing resource)

请求的资源不存在的通知:

HTTP/1.1 404 Not Found
Content-Type: text/html; charset=utf-8
Content-Length: 38217
Connection: keep-alive
Cache-Control: no-cache, no-store, must-revalidate, max-age=0
Content-Language: en-US
Date: Thu, 06 Dec 2018 17:35:13 GMT
Expires: Thu, 06 Dec 2018 17:35:13 GMT
Server: meinheld/0.6.1
Strict-Transport-Security: max-age=63072000
X-Content-Type-Options: nosniff
X-Frame-Options: DENY
X-XSS-Protection: 1; mode=block
Vary: Accept-Encoding,Cookie
X-Cache: Error from cloudfront

<!DOCTYPE html>… (contains a site-customized page helping the user to find the missing resource)

响应状态代码

HTTP 响应状态代码指示特定 HTTP 请求是否已成功完成。响应分为五类:信息响应、成功响应、重定向、客户端错误和服务器错误。

  • 200:好的。请求已成功。
  • 301:永久移动。此响应代码表示所请求资源的 URI 已更改。
  • 404:未找到。服务器找不到请求的资源。

其他HTTP 响应代码参考 常见的HTTP响应状态码 - 掘金 (juejin.cn)