WebSockets 协议:握手过程与数据帧解析

WebSocket:当浏览器和服务器开始“煲电话粥”

各位看官,咱们今天要聊聊 WebSocket,这玩意儿啊,就像浏览器和服务器之间的一条“煲电话粥”专线。想想咱们平时用浏览器上网,那都是“你问一句,我答一句”的模式,浏览器问服务器要个网页,服务器吭哧吭哧把网页送过来,完事儿,拜拜。下回再想聊,还得重新拨号,重新问一遍好。

这种模式,专业术语叫“请求-响应”,挺像古代的驿站传递消息,效率嘛,凑合,但不够实时。

但是,有些场景就受不了这种慢吞吞的节奏了,比如在线聊天、实时游戏、股票行情等等。你总不能让股票软件每隔几秒钟就刷新一次,看看有没有人发财了吧?这效率也太低了,搞不好还没刷新出来,钱都让人家赚走了。

所以,WebSocket 就应运而生了,它要做的,就是让浏览器和服务器之间建立一条长久的连接,就像两个人煲电话粥一样,一旦连上了,想说啥就说啥,不用每次都重新拨号。

那 WebSocket 是怎么实现这种“煲电话粥”的效果呢?这就得从它的“握手”过程和“数据帧解析”说起了。

“握手”:确认过眼神,才能开始聊天

想象一下,你给朋友打电话,总得先拨号、等待接通,然后互相确认身份,确定对方是你要找的人,才能开始正式聊天吧?WebSocket 的“握手”过程,就类似于这个过程。

1. 浏览器先抛个媚眼:HTTP Upgrade 请求

首先,浏览器会发送一个特殊的 HTTP 请求,这个请求叫做 HTTP Upgrade 请求。注意,这里还是 HTTP,WebSocket 并不是横空出世的,而是站在 HTTP 的肩膀上发展起来的。

这个请求长什么样呢?大概是这样的:

GET /chat HTTP/1.1
Host: example.com
Upgrade: websocket
Connection: Upgrade
Sec-WebSocket-Key: dGhlIHNhbXBsZSBub25jZQ==
Sec-WebSocket-Version: 13

咱们来解读一下:

  • GET /chat HTTP/1.1: 这表示浏览器想要访问服务器上的 /chat 路径,这通常是聊天应用的接口。
  • Host: example.com: 这是服务器的域名。
  • Upgrade: websocket: 重点来了!这句是告诉服务器,浏览器想要升级协议到 WebSocket。
  • Connection: Upgrade: 这句配合 Upgrade 一起使用,表示希望升级连接。
  • Sec-WebSocket-Key: dGhlIHNhbXBsZSBub25jZQ==: 这可不是随便写的,这是一个经过 Base64 编码的随机字符串。服务器会用这个字符串做一些加密运算,然后返回给浏览器,用来验证服务器是否支持 WebSocket 协议。你可以把它理解成一个暗号,只有双方都知道这个暗号的算法,才能成功“接头”。
  • Sec-WebSocket-Version: 13: 这是 WebSocket 协议的版本号。

简单来说,浏览器通过这个 HTTP 请求,告诉服务器:“嘿,老兄,我想跟你用 WebSocket 聊天,行不行?”

2. 服务器回应:确认眼神,建立连接

服务器收到浏览器的请求后,如果它也支持 WebSocket 协议,就会回应一个特殊的 HTTP 响应,这个响应长这样:

HTTP/1.1 101 Switching Protocols
Upgrade: websocket
Connection: Upgrade
Sec-WebSocket-Accept: s3pPLMBiHLiPVYyHO/qnhnKzht4=

咱们再来解读一下:

  • HTTP/1.1 101 Switching Protocols: 这表示服务器同意升级协议,状态码 101 告诉浏览器,协议已经切换成功。
  • Upgrade: websocket: 和请求一样,表示升级到 WebSocket 协议。
  • Connection: Upgrade: 同样是配合 Upgrade 使用。
  • Sec-WebSocket-Accept: s3pPLMBiHLiPVYyHO/qnhnKzht4=: 这才是重头戏!这个值是服务器根据浏览器发送的 Sec-WebSocket-Key 进行一系列复杂的加密运算后得到的。浏览器收到这个值后,会验证它是否正确,如果正确,就说明服务器确实支持 WebSocket 协议,并且双方都理解了对方的意思。

你可以把 Sec-WebSocket-Accept 理解成服务器的“签名”,浏览器通过验证这个签名,确认服务器是可靠的。

3. 握手完成:开始“煲电话粥”

当浏览器成功验证了 Sec-WebSocket-Accept 后,握手就完成了!浏览器和服务器之间建立了一条长久的连接,可以开始自由地发送和接收数据了,就像两个人成功拨通了电话,可以开始“煲电话粥”了。

“数据帧解析”:把消息拆成小包裹

握手完成后,浏览器和服务器就可以互相发送数据了。但是,数据并不是直接发送的,而是被拆分成一个个小的“包裹”,这些“包裹”就叫做 数据帧 (Data Frame)

为什么要拆分成小包裹呢?这就像咱们寄快递一样,如果东西太多,就得拆分成几个包裹,这样更容易运输和处理。WebSocket 的数据帧机制也是为了更好地管理和传输数据。

WebSocket 的数据帧格式比较复杂,咱们简化一下,说几个重要的部分:

  • FIN (1 bit): 表示这是不是消息的最后一个数据帧。如果是 1,表示是最后一个数据帧,整个消息发送完毕;如果是 0,表示还有后续的数据帧。
  • Opcode (4 bits): 表示数据帧的类型。常见的类型有:
    • 0x0: Continuation Frame,表示这是消息的延续帧,用于分片消息。
    • 0x1: Text Frame,表示数据是文本。
    • 0x2: Binary Frame,表示数据是二进制。
    • 0x8: Connection Close Frame,表示关闭连接。
    • 0x9: Ping Frame,用于心跳检测,客户端发送 Ping,服务器必须回复 Pong。
    • 0xA: Pong Frame,用于回复 Ping 请求。
  • Mask (1 bit): 表示数据是否经过掩码处理。客户端发送的数据必须经过掩码处理,服务器发送的数据则不需要。
  • Payload Length (7 bits, 7+16 bits, or 7+64 bits): 表示数据的长度。根据长度的不同,有三种不同的表示方式。
  • Masking Key (32 bits): 用于掩码处理的密钥。
  • Payload Data: 真正的数据。

举个例子:

假设浏览器要发送一个文本消息 "Hello, WebSocket!" 给服务器,这个消息会被拆分成一个或多个数据帧。如果是单个数据帧,那么:

  • FIN:1 (表示这是最后一个数据帧)
  • Opcode:0x1 (表示数据是文本)
  • Mask:1 (表示数据经过掩码处理)
  • Payload Length:假设 "Hello, WebSocket!" 的长度是 17 字节,那么 Payload Length 可能是 7+16 bits 的形式,表示长度超过 125 字节。
  • Masking Key:一个随机的 32 位密钥。
  • Payload Data:经过掩码处理后的 "Hello, WebSocket!" 数据。

服务器收到数据帧后,会根据数据帧的格式进行解析,取出数据,并进行反掩码处理,最终得到原始的文本消息 "Hello, WebSocket!"。

掩码处理:保护数据,防止“中间人攻击”

你可能会好奇,为什么要进行掩码处理呢?这是为了防止“中间人攻击”。

想象一下,如果没有掩码处理,攻击者可以截获客户端发送的数据,并篡改数据,然后发送给服务器。服务器收到被篡改的数据后,就可能做出错误的判断,导致安全问题。

掩码处理就像给数据穿上了一层“伪装”,让攻击者无法直接读取和篡改数据。只有服务器知道如何“脱掉伪装”,才能得到原始的数据。

心跳检测:保持连接,防止“假死”

WebSocket 连接是长连接,但是,如果长时间没有数据传输,连接可能会因为网络问题或者其他原因而断开,导致连接“假死”。

为了避免这种情况,WebSocket 提供了 心跳检测机制。客户端会定期发送 Ping 帧给服务器,服务器收到 Ping 帧后,必须回复 Pong 帧。如果客户端在一定时间内没有收到 Pong 帧,就认为连接已经断开,需要重新建立连接。

心跳检测就像给连接做了一个“体检”,定期检查连接是否健康,及时发现并解决问题。

总结:WebSocket,连接未来

WebSocket 协议就像一条高速公路,让浏览器和服务器之间可以快速、实时地进行数据传输。它在很多场景下都有着广泛的应用,比如:

  • 在线聊天: 让你可以实时地和朋友们聊天,不再需要频繁刷新页面。
  • 实时游戏: 让你可以流畅地玩游戏,不再担心延迟问题。
  • 股票行情: 让你可以实时地了解股票价格,抓住每一个赚钱的机会。
  • 在线协作: 让你可以和同事们实时地协作编辑文档,提高工作效率。

总而言之,WebSocket 协议正在改变我们使用互联网的方式,它让互联网更加实时、互动和高效。掌握 WebSocket 协议,就像掌握了一把通往未来互联网的钥匙。希望这篇文章能帮助你更好地理解 WebSocket 协议,并将其应用到你的项目中。

发表回复

您的邮箱地址不会被公开。 必填项已用 * 标注