自学 websocket(二):websocket 的工作流程解析

  • 本笔记一共分为4步
    1. 建立TCP连接
    2. 建立WebSocket连接
    3. 发送和接收数据
    4. 关闭WebSocket连接

1 建立TCP连接

  • WebSocket协议在浏览器和服务器之间建立了一个持久化的TCP连接。
  • 这个连接会一直保持到浏览器或服务器关闭连接为止。
  • 持久化的TCP连接使得浏览器和服务器之间可以随时发送数据,而不必像HTTP协议那样必须等待请求和响应。

1.1 从抓包结果分析

  1. 客户端向服务器发送SYN包(第一次握手):客户端发送一个SYN标志的TCP包,请求与服务器建立连接。
  2. 服务器向客户端发送SYN+ACK包(第二次握手):服务器收到客户端发送的SYN包后,会向客户端发送一个SYN+ACK标志的TCP包,表示已经收到客户端的请求,并同意建立连接。
  3. 客户端向服务器发送ACK包(第三次握手):客户端收到服务器发送的SYN+ACK包后,会向服务器发送一个ACK标志的TCP包,表示确认建立连接。此时,TCP连接已经建立完成,客户端和服务器可以进行数据传输。
  4. 客户端向服务器发送WebSocket握手请求:客户端会向服务器发送一个HTTP请求,包含WebSocket握手所需的信息,如Upgrade、Connection、Sec-WebSocket-Key等字段。
  5. 服务器向客户端发送WebSocket握手响应:服务器收到客户端的WebSocket握手请求后,会返回一个HTTP响应,包含WebSocket握手所需的信息,如Upgrade、Connection、Sec-WebSocket-Accept等字段。
  6. 客户端向服务器发送WebSocket Frame:WebSocket连接建立完成后,客户端和服务器可以在建立好的TCP连接上进行双向通信。此时,客户端会向服务器发送WebSocket Frame,包含需要传输的数据。

2 建立WebSocket连接

  • 在建立WebSocket连接之前,浏览器首先向服务器发送一个HTTP请求,请求升级到WebSocket协议。
  • 这个请求中包含了一些特殊的头部信息,告诉服务器浏览器要升级到WebSocket协议。
  • 如果服务器支持WebSocket协议,就会返回一个特殊的响应,告诉浏览器已经升级到WebSocket协议了。
  • 这个响应中包含了一些特殊的头部信息,告诉浏览器如何和服务器进行通信。
  • 这个过程称为WebSocket握手。

2.1 WebSocket握手

  1. 浏览器发送握手请求
  • 浏览器会向服务器发送一个HTTP请求,请求升级到WebSocket协议。请求头部中包含了一些特殊的头部信息,例如:
GET /chat HTTP/1.1
Host: server.example.com
Upgrade: websocket
Connection: Upgrade
Sec-WebSocket-Key: dGhlIHNhbXBsZSBub25jZQ==
Sec-WebSocket-Version: 13
************************************************
Upgrade:指明升级的目标为 websocket
Connection:说明需要升级
Sec-WebSocket-Key:是一个随机生成的字符串,用于计算
Sec-WebSocket-Version:用于协商 websocket 的版本
  1. 服务器返回握手响应
  • 如果服务器支持WebSocket协议,就会返回一个特殊的响应,告诉浏览器已经升级到WebSocket协议了
  • 浏览器会将 Sec-WebSocket-Accept 的值与本地计算的结果进行比较,如果一致,说明握手成功,可以开始建立WebSocket连接了
HTTP/1.1 101 Switching Protocols
Upgrade: websocket
Connection: Upgrade
Sec-WebSocket-Accept: s3pPLMBiTxaQ9kYGzzhZRbK+xOo=
*********************************************************
Upgrade和Connection字段指 服务器已经升级到WebSocket协议
Sec-WebSocket-Accept:是将Sec-WebSocket-Key和一个特定的GUID字符串拼接在一起,进行SHA-1哈希计算后生成的一个Base64编码的字符串
  1. 建立持久化的TCP连接
  • 在握手成功之后,浏览器和服务器之间就建立了一个持久化的TCP连接,可以随时发送数据

2.2 Sec-WebSocket-Accept 的生成过程

  1. 获取客户端请求中的 Sec-WebSocket-Key
  • 在WebSocket连接请求中,客户端会随机生成一个字符串 Sec-WebSocket-Key
  • 并将其放在请求头中的Sec-WebSocket-Key字段中
  1. 拼接GUID
  • 服务器 需要将一个特定的GUID字符串 "258EAFA5-E914-47DA-95CA-C5AB0DC85B11"和客户端请求中的Sec-WebSocket-Key字段的值 拼接在一起,生成一个新的字符串。
  1. 进行SHA-1哈希计算
  • 服务器对上一步中生成的字符串进行 SHA-1 哈希计算,得到一个20字节的哈希值,这个哈希值是一个二进制数据。
  1. 进行Base64编码得到 Sec-WebSocket-Accept
  • 服务器将上一步中得到的二进制哈希值进行Base64编码,生成一个字符串Sec-WebSocket-Accept
  • 这个字符串就是用于验证WebSocket连接请求的服务器响应头 Sec-WebSocket-Accept
    一个生成 Sec-WebSocket-Accept 的示例代码
import hashlib
import base64

# 获取客户端请求中的Sec-WebSocket-Key
client_key = 'dGhlIHNhbXBsZSBub25jZQ=='

# 拼接GUID和Sec-WebSocket-Key
guid = '258EAFA5-E914-47DA-95CA-C5AB0DC85B11'
concatenated = client_key + guid

# 进行SHA-1哈希计算
sha1 = hashlib.sha1()
sha1.update(concatenated.encode())
hash = sha1.digest()

# 进行Base64编码
accept = base64.b64encode(hash).decode()
print(accept)  # 输出:s3pPLMBiTxaQ9kYGzzhZRbK+xOo=
  • 为什么使用一个 固定GUID 的值与 client_key 拼接呢?
    • 使用固定的值与client_key拼接,是为了确保WebSocket连接请求的安全性和唯一性。
    • 这个固定的值是一个GUID(全局唯一标识符)字符串,它是一个128位的数字,可以保证全球范围内的唯一性。
    • 在WebSocket协议中,规定了一个固定的GUID字符串,即"258EAFA5-E914-47DA-95CA-C5AB0DC85B11",服务器需要将这个GUID字符串与客户端请求中的Sec-WebSocket-Key字段的值拼接在一起进行哈希计算。
    • 通过使用固定的GUID字符串,可以保证每个WebSocket连接请求都是唯一的,避免了请求被伪造的可能性。
    • 同时,使用SHA-1哈希算法进行计算,可以保证连接请求的安全性,避免了数据被篡改的风险。
    • 因此,WebSocket协议在设计时使用了GUID字符串与客户端请求中的Sec-WebSocket-Key字段的值拼接的方式,以确保WebSocket连接请求的安全性和唯一性。

3 发送和接收数据

  • 在建立WebSocket连接之后,浏览器和服务器就可以互相发送数据了。
  • 当浏览器要发送数据时,它会将数据封装在WebSocket帧中,并发送到服务器。
  • 服务器接收到帧后,解析出数据,并发送响应帧回到浏览器。
  • 浏览器接收到响应帧后,解析出数据,然后可以继续发送数据到服务器。
  • 这个过程可以不断地进行下去,直到浏览器或服务器关闭连接为止。

4 关闭WebSocket连接

  • 当浏览器或服务器想要关闭WebSocket连接时,它会发送一个特殊的帧,告诉对方它要关闭连接。
  • 对方接收到这个帧后,也会发送一个特殊的帧回应,告诉对方已经收到关闭请求。
  • 然后双方会分别关闭TCP连接,这样WebSocket连接就成功地关闭了。
  • 0
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值