45/ZWS
ZeroMQ WebSocket 协议 2.0
- 状态:草案
- 编辑:Doron Somech somdoron@gmail.com
ZeroMQ WebSocket 2.0 (ZWS2.0) 协议是 ZeroMQ 在 WebSocket 上的映射。
前言
版权所有 (c) 2020 Doron Somech
本规范是自由软件;您可以根据自由软件基金会发布的 GNU 通用公共许可证的条款重新分发和/或修改它;可以是许可证的第 3 版,或者(由您选择)任何更高版本。分发本规范是希望它有用,但没有任何担保;甚至不包括适销性或特定用途适用性的默示担保。有关更多详细信息,请参阅 GNU 通用公共许可证。您应该已经随本程序收到了 GNU 通用公共许可证的副本;如果没有,请参见 https://gnu.ac.cn/licenses。
本规范是一个自由开放标准,受数字标准组织(Digital Standards Organization)的共识导向规范系统管辖。
本文档中的关键词“MUST”(必须)、“MUST NOT”(不得)、“REQUIRED”(要求)、“SHALL”(应)、“SHALL NOT”(不应)、“SHOULD”(应该)、“SHOULD NOT”(不应该)、“RECOMMENDED”(建议)、“MAY”(可以)和“OPTIONAL”(可选)应按照RFC 2119中的描述进行解释。
目标
ZeroMQ WebSocket 协议 (ZWS) 是一种在 WebSocket 上进行对等方之间消息交换的传输层协议。本文档描述 ZWS/2.0。
实现
ZWS 连接在客户端和服务器之间成功完成 WebSocket 握手后开始。ZWS 消息是二进制 WebSocket 消息(消息操作码必须是二进制)。
握手
客户端和服务器之间的 WebSocket 连接发起和握手在 rfc6455 中定义。ZWS 握手请求 MUST(必须)包含至少一个协议作为 Sec-WebSocket-Protocol
的一部分。ZWS 定义了以下协议:
请求的主机和路径部分 MUST(必须)与用户在 connect 方法中设置的一致(例如 zmq_connect(s, "ws://server.example.com/zeromq")
)。
客户端请求示例
GET /zeromq HTTP/1.1
Host: server.example.com
Upgrade: websocket
Connection: Upgrade
Sec-WebSocket-Key: x3JJHMbDL1EzLkh9GBhXDw==
Sec-WebSocket-Protocol: ZWS2.0,ZWS2.0/NULL
Sec-WebSocket-Version: 13
Origin: http://example.com
服务器必须选择客户端协议中的一个,并在 WebSocket 握手期间将 Sec-WebSocket-Protocol
设置为所选协议。如果服务器不支持任何协议,服务器应该关闭连接(使用 BAD REQUEST、WebSocket 关闭控制消息或静默断开 TCP 连接)。
服务器回复示例
HTTP/1.1 101 Switching Protocols
Upgrade: websocket
Connection: Upgrade
Sec-WebSocket-Accept: HSmrc0sMlYUkAGmm5OPpG2HaGWk=
Sec-WebSocket-Protocol: ZWS2.0
无机制
ZWS2.0 的所有实现都必须实现无机制协议,除了 NULL 协议之外提供此协议的原因是针对那些未实现 ZMTP3.0 和各种机制的 ZeroMQ 端口。
无机制的 ZWS2.0 类似于 ZMTP/2,连接双方的第一个消息必须是路由 ID(身份),其余消息是常规消息。
正式 BNF
zws = *connection
connection = identity *message
identity = message-last
; A message is one or more frames
message = *message-more message-last
message-more = %x01 message-body
message-last = %x00 message-body
message-body = *OCTET
机制
ZWS 定义了 3 种可用的机制:
- NULL - 如ZMTP3.0 rfc中所述,不实现任何认证。
- PLAIN - 如ZMTP-PLAIN rfc中所述,实现简单的用户名和密码认证。
- BEARER - 尚未有规范,实现 bearer 认证。
格式 BNF
; The protocol consists of zero or more connections
zws = *connection
; A connection a handshake, and traffic
connection = handshake traffic
; The handshake consists of at least one command
; The actual grammar depends on the mechanism
handshake = 1*command
; Traffic consists of commands and messages intermixed
traffic = *(command | message)
; A command is a single frame
command = %x02 command-body
command-body = command-name command-data
command-name = OCTET 1*255command-name-char
command-name-char = ALPHA
command-data = *OCTET
; A message is one or more frames
message = *message-more message-last
message-more = %x01 message-body
message-last = %x00 message-body
message-body = *OCTET
帧格式
每个 ZeroMQ 帧映射到一个 WebSocket 消息。一个帧包含一个 FLAG 字节,后跟帧体。
标志位可以是:
- 0x00 - 最终消息
- 0x01 - 更多消息
- 0x02 - 命令消息
Socket 兼容性
ZWS 实现无需实现所有 socket 类型,可以选择要实现的 socket 类型。
实现 SHOULD(应该)根据接收连接的 socket 的类型强制执行传入连接具有有效的 socket 类型:
- PAIR 接受来自 PAIR 的连接。
- PUB 接受来自 SUB 的连接。
- SUB 接受来自 PUB 的连接。
- REQ 接受来自 REP 或 ROUTER 的连接。
- REP 接受来自 REQ 或 DEALER 的连接。
- DEALER 接受来自 REP、DEALER 或 ROUTER 的连接。
- ROUTER 接受来自 REQ、DEALER 或 ROUTER 的连接。
- PULL 接受来自 PUSH 的连接。
- PUSH 接受来自 PULL 的连接。
- SERVER 接受来自 CLIENT 的连接。
- CLIENT 接受来自 SERVER 的连接。
- RADIO 接受来自 DISH 的连接。
- DISH 接受来自 RADIO 的连接。
- SCATTER 接受来自 GATHER 的连接。
- GATHER 接受来自 SCATTER 的连接。
任何其他 socket 组合 SHOULD(应该)通过静默断开其他对等方连接来处理,并可能记录错误以用于调试目的。
发布-订阅
XPUB 和 XSUB socket 在协议层面上实现为 PUB 和 SUB socket。也就是说,XPUB 和 XSUB 仅是 API 构造。SUB socket 发送订阅消息时,以 0x01 字节开头,后跟订阅体;发送取消订阅消息时,以 0x00 字节 '0' 开头,后跟订阅体。
安全性
各种机制提供认证。然而,ZWS2.0 不尝试对线路进行加密。
客户端支持通过 SSL 隧道,指定 wss 而非 ws,例如 “wss://example.com”。
负载均衡器可能会在到达服务器之前终止 SSL。