原创:itsOli @前端一万小时
本文首发于公众号「前端一万小时」
本文版权归作者所有,未经授权,请勿转载!
本文节选自“语雀”私有付费专栏「前端一万小时 | 从零基础到轻松就业」
❗️❗️❗️
以下链接为本文最新勘误篇章——《【专栏试读】前后端交互 |(02)交互的规则、标准:HTTP——② HTTP 三次握手、URI、URL 和 URN》
1 HTTP 三次握手
1.1 基本概念
在正式讲解“HTTP 三次握手”之前,我们要弄清一个概念:
在“客户端”和“服务器”之间进行“HTTP 请求”发送和返回的过程中,我们首要的是需要去创建“TCP connection”这个东西!
❗️因为 HTTP 本身是不存在“连接”这个概念的,它只有“请求”和“响应”这两个概念!
而“请求”和“响应”都是“数据包”,“数据包”的传输需要一个“传输的通道”,这个“通道/连接”是在 TCP 里边去创建的。
“TCP 传输通道/连接”创建好了之后,其可以通过某种方式声明让它一直保持在那里。而后,我们的“HTTP 请求”就可以在这个“连接”的基础上去发送了。
当然,既然“连接”创建好之后会一直保持在那里,我们就可以在这个“TCP 连接”上去发送多个“HTTP 请求”。
❓我们为什么要让“TCP 连接”一直保持在那里呢? 答:因为“TCP 连接”有一个“三次握手”的过程,而这个过程会有三次网络消耗。若每连接完一次就关闭一次,必然带来很大的消耗和延迟!
“三次握手”表示在“客户端”和“服务端”之间有三次网络传输,只有三次网络传输完成后,“TCP connection”才会被创建,继而“HTTP 请求”才能被发送。
1.2 “三次握手”时序图
-
1️⃣首先,“客户端”发起一个“我要创建一个连接”这样的“数据包请求”给“服务端”:
SYN=1
:SYN 是一个“标志位”,表示创建了一个标有 SYN 的数据包;Seq=X
:同时会带一个 Seq,它等于一个数字,一般X=1
。
-
2️⃣然后,“服务端”接收到1️⃣发来的请求后,它就知道此时有客户需要跟我们建立连接了。“服务端”随即就会开启一个 TCP 的 socket 端口,同时返回给“客户端”一个数据包:
-
SYN=1
:这里的 SYN 也是一个标志位; -
ACK=X+1
:同时返回一个 ACK 标志位,其值等于1️⃣中“客户端”发过来的 Seq 的值 + 1;
(❗️二者合用,表示:“服务端”返回了一个标有 SYN/ACK 的数据包给“客户端”。) -
Seq=Y
:同时,“服务端”也要返回一个 Seq,其值等于一个新的数字 Y。
-
-
3️⃣最后,当“客户端”拿到2️⃣中“服务端”传递过来的数据后,它就知道了“服务端”已经允许它去创建一个“TCP 连接”了。“客户端”随即返回一个数据包给“服务端”:
ACK=Y+1
:ACK 是一个“标志位”,表示“客户端”发送了一个标有 ACK 的数据包给“服务端”,其值等于2️⃣中“服务端”发送过来的 Seq 的值 + 1;Seq=Z
:同时,“客户端”还要返回一个 Seq,其值等于一个新的数字。
❓为什么我们需要进行“三次握手”的过程呢?
答:这是为了防止“服务端”这边开启一些无用的“连接”。
我们知道,数据是需要经过光纤、各种中间代理服务器等进行传输,这就势必带来一定的“延时”。如果没有“三次握手”,“客户端”发起的**“创建连接”的请求1️⃣**在到达“服务端”后,“服务端”就会直接创建这个“连接”,并把相关数据返回给“客户端”。
这时,意外出现了:数据传输由于网络的原因,“数据”丢失了!“客户端”这边一直没接收到服务器返回的数据。而同时,“客户端”可能设置了一个“超时时间”——在多少时间内没接收到服务器返回的数据,就把“连接”关闭。而后又去发起新的数据请求。
但是,由于没有“三次握手”,我“服务端”这边也不知道你“客户端”压根就没接收到“数据”,你“客户端”也没给我任何反馈!此时,“服务端”的端口却是一直开着的,被白白浪费了。
所以,“三次握手”主要是为了规避网络传输过程中,由于延时而导致的“服务端”白白开销的问题。
1.3 用 Wireshark 直观说明“三次握手”的过程
以下我会使用一个强大的网络抓包工具 Wireshark 去抓取一些数据包进行说明。
❗️Wireshark 的具体安装的使用,我这里不作赘述,Windows 和 macOS 都有对应的官方安装包。这里先跟着我简单用起来,后边实际工作中需要哪个细节知识点再去深究即可。
首先,在终端输入以下命令行查看本机的 IP 地址(下方图片中红框标注的地方):
ifconfig
//Windows 系统是:
ipconfig
我这边局域网 IP 是 192.168.8.107
:
然后,打开安装好的 Wireshark,点击下图红框框住的地方,抓取本机目前 Wi-Fi 下的数据包:
随即,你便可以抓取到很多数据包(软件的左上角红色方块可以停止抓包),我这里挑了其中一个:
57030
表示本机的一个端口;443
表示“服务端”的一个端口。
仔细看看每一次握手“数据包”的相关信息,无论是是“标志位”的使用,还是各个“值”的关系,都和我们上边“三次握手”时序图里讲解的一模一样。
2 URI、URL 和 URN
2.1 定义
- URI:Uniform Resourse Identifier 统一资源标识符
- URL:Uniform Resourse Location 统一资源定位符
- URN:Uniform Resource Name 统一资源名称
URL 是使用浏览器等访问 Web 页面的时候需要输入的网页地址,如:
http://www.baidu.com
URI 是更通用的资源标识符,它由两个主要的子集构成:
- URL:通过描述资源的位置来描述资源;
- URN:通过名字来识别资源,和位置无关(目前使用的不多,了解一下即可)。
2.2 URL 的组成部分
我们常见的 URL 主要由三大部分组成:
- 方案,也就是我们常说的协议;
- 服务器位置;
- 资源路径。
例如:
https://www.yuque.com/olizhao/qdywxs
具体来说,通用的 URL 由 9 部分组成:
<scheme>://<user>:<password>@<host>:<port>/<path>;<params>?<query>#<hash>
-
<scheme>
:对于 Web 页面来说,最常用的协议就是 http 和 https; -
<user>:<password>
:user 和 password 现在不常见了,我们不会再在 URL 里明文书写用户名和密码,而是通过登录的方式去作用户的认证; -
<host>
:主机可以是 IP 地址或者域名; -
<port>
:端口号用来区分主机上的进程,方便找到 Web 服务器。
HTTP 默认端口是 80,可以不写,指提供 HTTP 服务的进程监听在 TCP 80 端口。
这好比银行的服务大厅有多个窗口,其中有个窗口提供外币兑换服务。为了让客户更便捷地找到窗口,银行总部规定默认情况下,各分行的第 80 个窗口提供外币兑换服务,这样需要兑换服务的客户只要找到任意一家分行,直奔 80 号窗口便是。
这里各分行地址可理解成 IP 地址,大厅的各个窗口可理解成端口。大厅各个窗口的服务内容可由大厅经理安排,这个经理可理解成服务器管理员。意思是虽然 HTTP 默认端口是 80,管理员也可以改成 81 端口,也可以把 80 端口改成 SSH 等其他服务。 -
<path>
:path 是资源的路径,也就是资源存放的位置。不一定和物理路径完全对应,符合 Web 服务器路由约定即可; -
<params>
:params 在一些协议中需要参数来访问资源。参数为“名/值对”,URL 中可以包含多个参数字段,它们相互之间,以及与路径的其余部分之间用分号;
分隔。
如:ftp.prep.ai.mit.edu/pub/gnu;type=d
——参数为type=d
,其中参数名为type
,值为d
。 -
<query>
:query 是 GET 请求最常用的传递参数方式。用字符?
将其与 URL 的其余部分分隔开来——如?a=1&b=2&=3
; -
<hash>
:hash 也称为片段,设计为标识文档的一部分,很多 MVVM 框架用作了路由功能。
有些资源类型,比如 HTML,除了资源级以外,还可以进一步划分。
比如一个带有章节的大型文本文档,URL 允许使用 hash 来表示资源内的一个片段,片段挂在 URL 右边,最前面有一个字符#
。
比如:http://www.baidu.com/tools.html#drills
这个例子中,片段引用了百度服务器上页面/tools.html
中的一个部分,这部分名字叫drills
。
下一篇我们集中讲解一个比较重要内容——HTTP 报文,只有弄懂这个知识点,后续的文章才能更轻松地阅读。
祝好,qdywxs ♥ you!