13/ZMTP
ZeroMQ 消息传输协议
- 状态:已废弃
- 编辑:Pieter Hintjens ph@imatix.com
ZeroMQ 消息传输协议 (ZMTP) 是一种传输层协议,用于在诸如 TCP 的连接传输层上在两个对等方之间交换消息。本文档描述了由 0MQ/2.x 代软件实现的 ZMTP/1.0。
许可证
版权所有 (c) 2009-2012 iMatix Corporation
本规范是自由软件;您可以在自由软件基金会发布的 GNU 通用公共许可证(任选第 3 版或任何更高版本)的条款下再分发和/或修改它。
本规范分发时希望它会有用,但不做任何担保;甚至没有适销性或特定用途适用性的默示担保。更多详细信息请参阅 GNU 通用公共许可证。
您应该已经随本程序收到了 GNU 通用公共许可证的副本;如果未收到,请参阅 https://gnu.ac.cn/licenses。
变更流程
本规范是一个自由开放标准(请参阅“自由开放标准的定义”),并由数字标准组织的一致性导向规范系统(COSS)管理(请参阅“一致性导向规范系统”)。
语言
本文档中的关键词“MUST”(必须)、“MUST NOT”(禁止)、“REQUIRED”(要求)、“SHALL”(应)、“SHALL NOT”(不应)、“SHOULD”(应该)、“SHOULD NOT”(不应该)、“RECOMMENDED”(推荐)、“MAY”(可)和“OPTIONAL”(可选)的解释应按照 RFC 2119 中的描述进行(请参阅“在 RFC 中用于指示需求级别的关键词”)。
目标
ZeroMQ 消息传输协议 (ZMTP) 是一种传输层协议,用于在诸如 TCP 的连接传输层上在两个对等方之间交换消息。本文档描述了由 0MQ/2.x 代软件实现的 ZMTP/1.0。
理论上,ZMTP 应该允许实现它的产品之间完全互操作。然而,必要语义的部分内容仅在 libzmq 的代码中定义。我们希望随着时间的推移,这些语义能够被正确地提取、抽象、文档化,并由独立的实现进行验证。
本规范的主要目标是允许独立实现栈与 libzmq 实现栈之间的互操作。次要目标是充当这个标准化过程的容器和催化剂。
架构
ZMTP 由以下层组成
- 一个帧层,它在底层传输上施加了大小前缀的规则性。
- 一个连接层,它允许两个对等方交换消息。
- 一个内容层,它定义了根据套接字类型如何格式化应用程序数据。
帧层
引言
帧层是 ZMTP 中所有内容的基础。基本传输层(例如 TCP 提供)是一个流。ZMTP 的帧层将其转换为一系列帧,可以是任一方向。帧指定了长度,因此对等方可以安全地拒绝过大的帧。ZMTP 的帧设计针对带宽和性能进行了优化。
帧用于创建结构化消息,而不是将大消息分解成片段。ZMTP 假定对等方将读取和处理消息的所有帧,或者完全不处理。帧特别用于将消息内容与消息地址信封分离(参见内容层)。
无论连接上正在发生什么工作,帧层都是一致的。也就是说,它可以完全根据线路上发送的信息进行解释。
规范
一个 ZMTP 消息由 1 个或多个帧组成。
一个 ZMTP 帧由一个长度字段、一个标志字段以及一个长度为(长度 - 1)字节的帧体组成。注意:长度包含标志字段,因此空帧的长度为 1。
对于长度为 1 到 254 字节的帧,长度 SHOULD BE(应该)编码为一个字节。帧的最小有效长度为 1 字节,因此长度为 0 是无效的,并且此类帧 SHOULD be(应该)静默丢弃。
对于长度为 255 或更大的帧,长度 SHALL BE(应)编码为一个值为 255 的字节,后跟编码为网络字节序的 64 位无符号整数长度。对于长度为 1 到 254 字节的帧,此编码 MAY be(可)用于。
标志字段由一个包含各种控制标志的字节组成。位 0 是最低有效位。
-
位 0 (MORE):后续更多帧。值为 0 表示没有更多帧要跟随。值为 1 表示将有更多帧跟随。对于仅包含一个帧的消息,MORE 标志 MUST be(必须)为 0。
-
位 1-7:保留。位 1-7 保留供将来使用,并且 SHOULD be(应该)为零。
以下 ABNF 语法定义了一个 ZMTP 消息
message = *more-frame final-frame
more-frame = length more body
final-frame = length final body
length = OCTET / (%xFF 8OCTET)
more = %x01
final = %x00
body = *OCTET
以下图示显示了长度为 1 到 254 字节的帧的布局
+----------------+
Octet 0 | Length |
+----------------+
Octet 1 | Flags |
+----------------+- ... ---------------------+
Octets 2+ | Body Length - 1 octets |
+------------------ ... ---------------------+
以下图示显示了长度为 255 或更多字节的帧的布局
+----------------+
Octet 0 | 0xff |
+----------------+- ... ---------------------+
Octets 1-8 | Length 8 octets |
+------------------ ... ---------------------+
Octet 9 | Flags |
+----------------+- ... ---------------------+
Octets 10+ | Body Length - 1 octets |
+------------------ ... ---------------------+
连接层
引言
连接层提供了一种方式,使对等方在 TCP 连接时互相识别。一个 ZMTP 连接等同于一个 TCP 连接。如果对等方断开并重新连接,这被视为两个独立的 ZMTP 连接。
规范
一个 ZMTP 连接是双向且异步的。也就是说,任一对等方 MAY send(可发送)消息给另一个对等方在任何时间。
连接的每一侧由一个问候消息,后跟零个或多个内容消息组成。内容消息根据内容类型进行格式化,如内容层规范中所解释。
对等方 SHALL send(应发送)一个问候消息,由一个匿名消息或一个身份消息组成。匿名问候消息由一个空字符串组成。这告诉另一个对等方,此连接没有持久性,连接结束时所有关联资源都可以被删除。身份问候消息由一个 1 到 255 字节的唯一字符串组成。这告诉另一个对等方将资源与该身份关联,并在连接结束时无限期地持有它们。
身份 SHOULD NOT(不应该)以零字节开头,零字节保留用于对等方内部使用。对等方 MAY reject(可拒绝)身份,并且 SHOULD be cautious(应该谨慎)对待无限期持有资源的成本。
以下 ABNF 语法定义了 ZMTP 连接的任一方向
connection = greeting content
greeting = anonymous / identity
anonymous = %x01 idflags
identity = length idflags (%x01-ff) *OCTET
idflags = %00
身份帧的标志字节 (idflags) SHALL not be(不应)验证,并且 SHOULD be(应该)设置为零。
内容层
引言
跨连接发送的 ZMTP 内容消息的格式和语义取决于该连接方向的内容类型,内容类型未在协议中指定,但必须由双方对等方假定。
以下 ABNF 语法定义了 ZMTP 内容
content = *broadcast / *addressed / *neutral
广播内容
广播内容用于发布者和订阅者之间。发布者 SHALL send(应发送)广播内容。订阅者 SHALL NOT send(不应发送)任何内容。
以下 ABNF 语法定义了 ZMTP 广播内容
broadcast = message
接收方 MAY filter(可过滤)消息。可以使用任何匹配机制(前缀、通配符、正则表达式)。ZMTP 没有标准化这一点,尽管当前的 ZeroMQ 实现使用了前缀匹配。
寻址内容
寻址内容用于请求-回复链中的对等方之间。在请求-回复链中,任一对等方 MAY send(可发送)寻址内容给任何其他对等方。
以下 ABNF 语法定义了 ZMTP 寻址内容
addressed = envelope message
envelope = *more-frame delimiter
delimiter = %x01 more
对等方 SHOULD be used(应该)以下列方式使用信封
- 当一个对等方向另一个对等方发送请求时,它应该发送一个至少包含分隔符的信封。
- 当一个对等方将请求从一个对等方转发给另一个对等方时,它应该将原始发送对等方的身份前置到信封中(作为一个身份帧)。
- 当一个对等方接受请求并用回复响应时,它应该解开并保存包括分隔符在内的完整地址信封,然后将剩余消息传递给应用程序,然后用包括分隔符在内的完整地址信封重新包装应用程序的响应。
通过这种方式,一系列对等方在转发请求时可以将地址推入信封,并在路由回复时将地址从信封中弹出。
中立内容
中立内容用于不需要路由的对等方之间。任一对等方 MAY send(可发送)中立内容给另一个对等方,尽管特定的对等方实现 MAY ignore(可忽略)来自其对等方的内容。
以下 ABNF 语法定义了 ZMTP 中立内容
neutral = message
完整 ZMTP 语法
以下 ABNF 语法定义了完整的 ZMTP 协议
zmtp = *connection
connection = greeting content
greeting = anonymous / identity
anonymous = %x01 idflags
identity = length idflags (%x01-ff) *OCTET
idflags = %00
message = *more-frame final-frame
more-frame = length more body
final-frame = length final body
length = OCTET / (%xFF 8OCTET)
more = %x01
final = %x00
body = *OCTET
content = *broadcast / *addressed / *neutral
broadcast = message
addressed = envelope message
envelope = *more-frame delimiter
delimiter = %x01 more
neutral = message
已知问题
该协议没有版本号。这在 ZMTP 的后续版本中已得到修复,建议实现者至少实现 ZMTP/2.0。
在线路格式中没有内容类型的交换或验证。也就是说,对等方必须事先知道它期望从另一个对等方获得的内容类型,以便将其内容正确地解释为广播、寻址或中立类型。这可以通过如上文提出的那样,在连接头部添加内容类型指示符来解决。
长度字段的规范令人惊讶(甚至让阅读规范的专家感到困惑)。它不应该包括标志字段,也不应该包括其他可能的头部字段。这将允许使用长度为零来指定零长度的体。
“身份不能以二进制零开头”的限制继承自软件实现,并且在 ZMTP 中没有明显的语义作用。这一点应该得到澄清。
安全性
ZMTP/1.0 没有尝试提供安全性,应用程序 MAY layer on top(可在其之上分层实现)。