WebSocket

 

WebSocket协议

协议概述

  • WebSocket是一种网络传输协议,可在单个TCP连接上进行全双工通信,位于OSI模型应用层。WebSocket协议在2011年由IETF标准化为RFC 6455,后由RFC 7936补充规范。Web IDL中的WebSocket API由W3C标准化。
  • WebSocket使得客户端和服务器之间的数据交换变得更加简单,允许服务端主动向客户端推送数据。在WebSocket API中,浏览器和服务器只需要完成一次握手,两者之间就可以创建持久性的连接,并进行双向数据传输。
  • WebSocket协议规范将ws(WebSocket)和wss(WebSocket Secure)定义为两个新的统一资源标识符(URI)方案[4],分别对应明文和加密连接。

与Http协议的关系

  • 有交集,但不是全部。
  • HTTP有1.1和1.0,也就是所谓的keep-alive,把多个HTTP请求合并为一个,但是Websocket其实是一个新协议,跟HTTP协议基本没有关系,只是为了兼容现有浏览器的握手规范而已,也就是说它是HTTP协议上的一种补充。
  • WebSocket是一个持久化协议。HTTP是非持久化协议,即Request=Response。

握手协议

GET /chat HTTP/1.1
Host: server.example.com
Upgrade: websocket
Connection: Upgrade
Sec-WebSocket-Key: x3JJHMbDL1EzLkh9GBhXDw==
Sec-WebSocket-Protocol: chat, superchat
Sec-WebSocket-Version: 13
Origin: http://example.com
  • Connection:标识此次链接协议需要升级
  • Upgrade:升级的目标协议
  • Sec-WebSocket-Key:值为经过Base64转换的长度为16字节的一组数据
HTTP/1.1 101 Switching Protocols
Upgrade: websocket
Connection: Upgrade
Sec-WebSocket-Accept: HSmrc0sMlYUkAGmm5OPpG2HaGWk=
Sec-WebSocket-Protocol: chat
  • Sec-WebSocket-Accept:Base64(SHA-1(Sec-WebSocket-Key + "258EAFA5-E914-47DA-95CA-C5AB0DC85B11"))

报文结构

  • FIN:标识这一帧数据是否是该分块的最后一帧。
    • 1 为最后一帧
    • 0 不是最后一帧,需要分为多个帧传输
  • RSV1, RSV2, RSV3:默认值为0。
    • 除非协议扩展(Extensions)声明了非0的值的含义。如果服务端收到非0的值,并且没有相应的定义,那么服务端将直接终止连接
  • Opcode: 操作码,也就是定义了该数据是什么,如果不为定义内的值则连接中断。占四个位,可以表示0~15的十进制,或者一个十六进制。
    • 0x0 表示一个继续帧
    • 0x1 表示一个文本帧
    • 0x2 表示一个二进制帧
    • 0x3-0X7 非控制帧保留
    • 0x8 表示一个连接关闭
    • 0x9 表示一个PING
    • 0xA 表示一个PONG
    • 0xB-0xF 控制帧预留
  • Mask:是否存在掩码。
    • 客户端向服务器发送,必须掩码,值为1
    • 服务端向客户端发送不需掩码,值为0
  • PayLoad Length:表示Payload data的总长度。占7位,或者7+2个字节、或者7+8个字节。
    • 0-125,则是payload的真实长度
    • 126,则后面2个字节形成的16位无符号整型数的值是payload的真实长度,125<数据长度<65535
    • 127,则后面8个字节形成的64位无符号整型数的值是payload的真实长度,数据长度>65535
  • Masking-Key:当masked为1的时候才存在,为4个字节,否则为0,用于对我们需要的数据进行解密。
  • PayLoad Data:定义为"Extension data" 后接"Application data"。所以字节长度是两者之和。
  • Extension Data:在握手时就需要协商的扩展协议,需要指定扩展数据的长度或者如何计算长度。如若没有,则扩展数据为0字节。如有,则扩展数据会被包括在Payload中。
  • Application Data:任意数据内容,数据长度是Payload长度减去Extension长度。

心跳机制

  • 通俗来讲:就像心跳一样,每隔固定时间,来告诉服务器,客户端还“活着”。
  • 为什么要有心跳机制?
    • 客户端断网时,服务器端并没有感知。这样导致服务器继续向客户端发送数据包,并且这些数据可能会丢失。且服务端会维持这次连接,从而浪费服务端资源。
    • 进一步,可以通过心跳机制来判断客户端的在线状态,客户端可以尽快重连。
  • 具体实现
    • Ping:Opcode为0x9,可以包含Application Data,双端都可以发送且需立即回复Pong,用来探活。如果服务端在收到Ping时,已经发送了close,则不用发送Pong。
    • Pong:Opcode为0xA,Pong可以只响应最近一次的Ping。Pong必须包含Ping对应的Application Data。

握手时序图

抓包分析

TCP握手

数据传递

断开链接

  • 可以看出61475端口一开始为HTTP服务的,后来由于101返回码,61475 端口转为 websocket 的 5001 端口号,服务端的8080端口对接客户端的5001端口号。关闭websocket时,由 61475 端口号发起关闭 5001 请求,与此同时 61475 端口和 服务端的8080端口通信,告诉服务端我要关闭端口,成功后61475 再告诉 5001 端口,我关闭成功了。整个关闭流程结束。

WebSocket的优点

  • 较少的控制开销。相对于HTTP请求每次都要携带完整的头部,此项开销显著减少了。
  • 更强的实时性。由于协议是全双工的,所以服务器可以随时主动给客户端下发数据。
  • 保持连接状态。与HTTP不同的是,Websocket需要先创建连接,这就使得其成为一种有状态的协议,之后通信时可以省略部分状态信息。而HTTP请求可能需要在每个请求都携带状态信息(如身份认证等)。
  • 更好的二进制支持。Websocket定义了二进制帧,相对HTTP,可以更轻松地处理二进制内容。
  • 可以支持扩展。Websocket定义了扩展,用户可以扩展协议、实现部分自定义的子协议。
  • 更好的压缩效果。相对于HTTP压缩,Websocket在适当的扩展支持下,可以沿用之前内容的上下文,在传递类似的数据时,可以显著地提高压缩率。
  • 支持跨域访问,没有同源限制。服务端可以根据Origin字段决定是否通过该次请求。

WebSocket与Socket之间的关系

  • 通常所说的Socket API,是指操作系统中(也可能不是操作系统)提供的对于传输层(TCP/UDP)抽象的接口。
  • Socket 其实并不是一个协议,它工作在 OSI 模型会话层(第5层),是为了方便大家直接使用更底层协议(一般是 TCPUDP )而存在的一个抽象层。
  • 而 WebSocket 则不同,它是一个完整的 应用层协议,包含一套标准的 API

WebSocket与HTTP的比较

  • 相同点
    • 都是基于TCP的应用层协议;
    • 都使用Request/Response模型进行连接的建立;
    • 在连接的建立过程中对错误的处理方式相同,在这个阶段WS可能返回和HTTP相同的返回码;
    • 都可以在网络中传输数据。
  • 不同点
    • WS使用HTTP来建立连接,但是定义了一系列新的header域,这些域在HTTP中并不会使用;
    • WS的连接不能通过中间人来转发,它必须是一个直接连接;
    • WS连接建立之后,通信双方都可以在任何时刻向另一方发送数据;
    • WS连接建立之后,数据的传输使用帧来传递,不再需要Request消息;
    • WS的数据帧有序。

常见的应用场景

  • 即时通信
  • 在线游戏
  • 视频弹幕
  • 直播间
  • 股票行情
  • 配置变更下发
  • 在线调试
posted @ 2021-08-20 11:10  宋同学shl  阅读(180)  评论(0)    收藏  举报