手写HTTP服务器 —— HTTP 协议简介

2020-10-27   13 次阅读


前言:

以下内容来自我购买的极客时间课程 《深入拆解 Tomcat&Jetty》,与 MDN 《HTTP 概述》章节,我做了整理与增加了部分个人理解。

1. HTTP 协议简单概述

HTTP 被设计于20世纪90年代初期,是一种 可扩展的协议 。它是 应用层 的协议,通过 TCP,或者 TLS-加密的TCP 连接来发送,理论上任何可靠的传输协议都可以使用。因为其良好的扩展性,时至今日,它不仅被用来传输超文本文档,还用来传输图片,视频,或者向服务器发送如HTML表单这样的信息。HTTP还可以根据网页需求,仅获取部分Web文档内容更新网页。

协议中存在两种角色:服务端客户端

客户端向服务端发出请求 request ,服务端响应 response 客户端请求,最终达成数据交换。

A Web document is the composition of different resources

2. HTTP 的本质

HTTP 协议是用来在客户端与服务端之间传输数据的 应用层 协议。

HTTP 基于 TCP/IP 进行数据传输,HTTP 并不涉及 数据包(Packet) 传输,而是 规定了客户端与服务端之间的通信格式

当浏览器需要获取服务器上的某个资源,例如一个 HTML 文本时,浏览器需要做两件事:

  1. 与服务器建立 Socket 连接。
  2. 生成请求数据,通过 Socket 发送到服务器。

而 HTTP 的本质是:

  • 浏览器与服务器之间约定好的 通信格式

3. HTTP 工作原理

下面是一张 HTTP 请求的示意图:

下面是详细解读:

  1. 用户通过 浏览器 进行了一个操作,比如输入网址并回车,或者点击了一个链接,接着浏览器获取到了这个事件。【通过浏览器作为客户端,触发一次 HTTP 请求】
  2. 浏览器服务端 发出 TCP 连接请求。【开始建立底层连接,这里涉及到 TCP/IP 知识与连接的建立过程】
  3. 服务器接受浏览器的连接请求,经过三次握手后 建立连接 。 【1. 建立连接】
  4. 浏览器将请求数据打包成一个 HTTP 协议的数据包。 【2. 客户端准备数据】
  5. 浏览器将数据包通过网络传输到服务器。【3. 发送数据】
  6. 服务器获取浏览器的请求数据包,同样用 HTTP 协议解包,获取到客户端的意图。【4. 服务端接收请求数据】
  7. 根据客户端意图,服务器 进行对应的逻辑处理。【服务端根据客户端的请求开始处理业务逻辑】
  8. 服务器 将响应结果(可能是 HTMl 或者图片等媒体)按照 HTTP 协议打包。【服务端准备 response 数据】
  9. 服务器将响应数据包通过网络传给浏览器。【服务端将 response 传递给 客户端】
  10. 浏览器 拿到响应包后用 HTTP 协议解包。【客户端解析 response 数据】
  11. 浏览器 将解析后的数据渲染到页面上。【将数据渲染到页面上】

4. HTTP 的特性

1. HTTP 是无状态协议

HTTP是无状态的 :在同一个连接中,两个执行成功的请求之间是没有关联联系的。

2. HTTP 可扩展性

在HTTP/1.0中出现的 HTTP headers 让协议扩展变得非常容易。只要服务端和客户端在 headers 达成语意一致,客户端新增加的 header 能够被服务端解析,就完成了对 HTTP 的扩展。

3. HTTP 会话

基于上面的 HTTP 本身是 无状态的协议 ,但是某些场景下我们需要记录用户的一些数据,所以对 HTTP 头部进行扩展,增加 HTTP Cookie 字段,每次请求时都将 Cookie 发送给 服务端,保证了状态信息的传递。

4. HTTP 底层连接

由于 HTTP 是 应用层 的协议,而连接由 传输层 协议进行控制。

常用的 传输层协议 有两种:

  • TCP ---> 面向连接的可靠协议
  • UDP ---> 非可靠协议

HTTP 依赖面向连接的 TCP 进行消息传递,但是连接并不是必须的。

5. HTTP 「请求」和「响应」的组成部分

1 请求:

HTTP 请求数据由三部分组成:请求行请求头请求正文

  • 请求行: 包括了 请求方法URL 地址,以及 HTTP 协议版本

如下图,可以看到这是一个 POST 请求, URL 是 /serv/v1/my/data ,HTTP 版本是 1.1

image-20200917123548579

HTTP headers let the client and the server pass additional information with an HTTP request or response. An HTTP header consists of its case-insensitive name followed by a colon (:), then by its value. Whitespace before the value is ignored.

HTTP标头使 客户端服务器 可以通过HTTP请求或响应传递其他信息。 HTTP标头由不区分大小写的名称,后跟冒号(:)和值组成。该值之前的空白将被忽略

image-20200917122935127

  • 请求正文: 本次请求提交到服务端的具体数据。

![image-20200917123202260](/Users/xuyanxin/Library/Application Support/typora-user-images/image-20200917123202260.png)

响应:

响应内容也一样,包含 状态响应头响应主体

状态行 包括 HTTP 版本,状态码状态信息,状态信息可以由 服务端 自行设定,比如这里的 OK 就是服务端自己添加的返回数据。

image-20200917123507955

返回头:

image-20200917122944429

返回体:

image-20200917123226104

出现背景: HTTP 协议的特性 ---> 无状态 ,导致请求之间没有关联关系,这有优点,但是在某些场景下也会出现不足:

  • 例如电商中的购物车场景,如果不使用 CookieSession,那么登录之前添加在购物车中的东西登录后就没了。

所以需要让 请求之间建立联系 ,并且服务端需要根据这个标识知道请求来自哪个具体用户.

CookieHTTP 请求头中的一个字段,Web 应用可以将用户标识或者其他信息存储在 Cookie 中。用户经过验证后,每次 HTTP 请求中的请求头,服务器通过 Cookie 中的标识识别用户。

Cookie 的本质 :存储在用户 本地 的文件,里面包含了每次请求都需要传递的信息。

缺点:

  • 以明文的方式存储在本地,并且信息通常与用户密切相关,导致安全性存在问题。

2. Session

基于 Cookie 带来的隐患:存储在用户本地,于是有了 Session 技术,Session 存储在服务器中,里面保存用户的状态。

当用户发起请求时,服务端将用户的请求与用户的 Session 通过 Cookie 关联起来 ,在 Cookie 中填充一个用户的 Session ID 充当桥梁,这个 ID 与 用户信息没有直接关系,从而解决了安全问题。

具体流程:

  • 服务器创建 Session 的同时生成一个与 Session 对应的唯一 ID
  • 浏览器再次请求时将 Session ID 保存在 Cookie 中发送给服务器,服务器通过 Session ID 找到对于的 Session,获取 Session 中保存的内容

优点:

  • 1、安全性。
  • 2、节约流量,内容都在 Session 中,用户请求时只需要发送 Session ID。

3. Session 的创建与存储

不同语言实现的应用程序有不同的创建 Session 的方法。

Java 中,Web 应用程序调用 HttpServletRequestgetSession() 方法时,由 Web容器(如 Tomcat)创建。

Web 容器同时提供多种持久化方案存储 Session,通常会采用高性能的存储方式,例如 Redis,并且需要考虑 集群部署,避免单点故障导致 Session 不可用。

同时需要开启线程轮询,当 Session 过期后置为失效状态。

小结:

  • 创建:Web 容器
  • 保存:Web 容器
  • 维护:Web 容器

这些逻辑都需要 Web 容器去实现。

Q.E.D.

知识共享署名-非商业性使用-相同方式共享 4.0 国际许可协议

最是人间留不住,曾是惊鸿照影来。