网络通信 频道

小菜学网络之WebSocket协议

  Web应用 采用 HTTP 协议进行通信:客户端向服务器发送 HTTP 请求,服务器对请求进行处理后,向客户端回复 HTTP 响应。换句话讲,HTTP 协议只能客户端主动发起请求,服务器被动进行响应。  图片

  不少应用场景要求服务主动向客户端进行推送,这时 HTTP 协议就有点捉襟见肘了。举个例子,为实现 Web 聊天室功能,当新消息到达时,服务器必须向客户端推送通知。只用 HTTP 协议来实现,我们必须在客户端做轮询。

  轮询有个致命的缺陷——性能比较差:如果轮询频率很高,服务器要消耗很多资源;但如果控制轮询频率,应用消息通知的实时性又大打折扣。

  很显然,服务器主动向客户端推送数据,也是一个非常常见的应用场景,最好能从网络协议层面进行支持。为此,计算机网络先驱们设计了 WebSocket 协议。

  WebSocket 协议,顾名思义为 Web 应用引入了 套接字( socket )通信能力。Websocket 是一种应用层协议,以 TCP 为底层传输协议,为通信双方提供了一个 全双工 的信道。

  为了兼容 Web 主流应用协议 HTTP ,WeSocket 复用 80 和 443 端口,并使用 HTTP 请求来建立连接(配合 Upgrade 头部)。因此,WebSocket 可以兼容现有的 HTTP代理 和中间件,例如 Nginx 。

  URL

  和 HTTP 协议一样,WebSocket 服务器地址也用 URL 表示,只是协议部分为 ws 或 wss 。例如:

  连接建立

  客户端先通过 TCP 协议连到服务器,然后通过 TCP 连接向服务器发送 HTTP 请求。请注意,HTTP 请求头中要带 Upgrade 头部,告诉服务器将连接升级到 WebSocket 协议:

  服务器接到请求后,检查 Upgrade 头部,发现客户端想将连接协议升级到 WebSocket 。如果应用服务器支持 WebSocket ,它便回复 101 状态码,表示同意切换协议:

  HTTP 请求和响应交互完毕后,通信双方就可以在 TCP 连接上互相发送 WebSocket 报文了。

  数据帧

  连接建好后,通信双方就可以用 WebSocket 协议来发送数据了。WebSocket 将数据组织成一系列帧( frame )来传输,一条应用层消息可以封装成一个或多个数据帧。数据帧报文结构如下所示:

  标志位 ,占 4每个标识占一位;

  a.FIN

  b.RSV1 、RSV2 和 RSV3

  a.0 这是前面数据帧的续帧(一个消息封装成多个帧时);

  b.1表示这是一个文本帧;

  c.2 表示这是一个二进制( binary )帧;

  d3~7 保留,未来可以分配给新的非控制( non-control )帧;

  e.8 表示这是一个连接关闭( close )帧;

  f.9 表示这是一个 ping 帧;

  g.10 表示这是一个 pong 帧;

  h.11~15 保留,未来可以分配给新的控制( control )帧;

  MASK 位,表示 承载数据( payload data )是否做掩码处理,1 表示掩码处理,0 表示不做掩码处理(客户端发的帧必须做掩码处理,主要出于避免网络中间件混淆和安全上的考虑);

  数据长度( payload len ),占 7 位,用来表示数据负载的长度(以字节为单位);

  a.该字段小于 126 时,该字段直接表示数据长度,其后的扩展字段为空( 0 字节),可表示 0~125 字节的数据;

  b.当该字段等于 126 时,数据长度由其后的扩展字段表示,这是扩展字段为 2 字节,可表示长度为 126~65535 字节的数据;

  c.

  扩展数据长度( extended payload len ),占用 0 、2 或 8 字节,由前一个字段决定;

  掩码Key( masking key ),数据帧开启掩码处理时( MASK=1 )才有,占用 4 个字节,用于掩码计算;

  承载数据( payload data ),即数据帧承载的应用层数据;

  数据长度字段比较复杂,需要分三种情况讨论,分别举个例子帮助理解:  图片

  注意到,为了简化报文,我们假设 MASK=0 ,未启动掩码处理。

  WebSocket 帧结构看似复杂,但无非还是先分成 头部 和 数据 两大部分,其中头部保存 数据类型(操作码)和 数据长度 ,而操作码又分成控制和非控制两种。

  控制帧则继续分为 close 、ping 和 pong 三种:close 用于关闭连接;ping 和 pong 用于检测连接状态,检测方发 ping ,被检测方回复 pong 。这样当应用暂时没有数据要发送时,ping/pong 可让连接保持活跃。当连接断开时,也能及时检测到。

  而非控制帧则分为 text 和 binary 两种,上层应用使用文本协议,则选 text ;使用二进制协议,则选 binary 。

  总结

  WebSocket 兼容 HTTP 协议,借助 HTTP 请求建立连接;

  WebSocket 通信分为两个阶段:

  连接建立阶段:使用 HTTP

  数据通信阶段:使用 WebSocket

  WebSocket 通信报文为 帧 ,一个帧由 头部 和 数据 两部分组成;

  WebSocket 帧头部保存 操作码 和 数据长度 等字段;

  根据操作码不同,WebSocket 帧可以分成 控制帧 和 非控制帧 两类;

  WebSocket 控制帧分为 close 、ping 和 pong 三种;

  ping / pong 控制帧用于连接保活和状态检测;

  close 控制帧用于关闭连接;

  WebSocket 非控制帧分为 文本帧 和 二进制帧 两种;

0
相关文章