ZeroMQ消息传输协议(v1)

看了ZMTP 2.0的协议介绍,我们也看看1.0,想看原文的在这里。

目标

ZeroMQ消息传输协议(ZMTP)是一种传输层协议,用于通过连接的传输层(如TCP)在两个对等程序之间交换消息。本文档描述了由0MQ/2.x实现的ZMTP/1.0。

理论上,ZMTP应该允许实现它的程序之间的完全互操作性。但是,部分必要的语义只在libzmq的代码中定义。我们希望随着时间的推移,这些语义将被正确地提取、抽象、文档化,并通过独立的代码进行验证。

该规范的主要目标是允许独立堆栈和libzmq堆栈之间的互操作性。第二个目标是充当这个标准化过程的资料架和催化剂。

体系结构

ZMTP由以下层组成:

  • 一个组帧层(framing layer),它对底层传输施加了一个带有大小前缀的规则。
  • 允许两个对端交换消息的连接层(connection layer)。
  • 内容层(content layer),根据套接字类型定义如何格式化应用程序数据。

组帧层

序言

组帧层是ZMTP中所有内容的基础。基本传输层(例如由TCP提供)是一个流。ZMTP的帧层将其转换为一系列帧(frame),不分传输方向。帧是指定长度的,因此对端可以安全地拒绝超大的帧。ZMTP的帧设计针对带宽和性能进行了优化。

组帧用于创建结构化消息,而不是将大型消息分解成片段。ZMTP假设对端将读取和处理消息的所有帧,或者完全一帧都不读取和处理。帧特别用于将消息内容从消息地址信封中分离出来(参见内容层)。

无论连接上发生了什么工作,组帧层都是一致的。也就是说,它可以从网线上发送的信息中完全解释。

规范

ZMTP消息由1个或多个帧组成。

一个ZMTP帧由一个长度(length)、一个标志(flag)字段和一个(长度- 1)字节的帧体组成。注意: 长度包括flags字段,所以空帧的长度为1。

对于长度为1到254字节的帧,长度应该被编码为单个字节。帧的最小有效长度是1字节,因此长度为0是无效的,这样的帧应该被默默地丢弃。

对于长度为255或更大的帧,长度应该被编码为一个值为255的单字节体,然后是按网络字节顺序编码为64位无符号整数的长度。对于长度为1到254字节的帧,也可以使用这种编码。

标志字段由包含各种控制标志的单个字节组成。位0是最低位。

  • 位0 (MORE): 后面还有帧。值为0表示没有更多的帧。值为1表示后面还会有帧。对于由单帧组成的消息,MORE标志必须为0。
  • 位 1-7: 保留。位1-7为将来使用保留,应该为零。

下面的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连接是双向异步的。也就是说,任何一端都可以在任何时间向另一端发送消息。

连接的每一端都包含一个问候语(greeting),后面跟着零个或多个内容。内容消息是根据内容类型进行格式化的,如内容层规范中所述。

一端(peer)应发送由匿名(anonymous)或身份标识(identity or ID)组成的问候语。匿名问候语由空字符串组成。这将告诉另一端,该连接没有持久性,当连接结束时,与之关联的所有资源都将被删除。有身份标识(ID)的问候语由1到255字节的唯一字符串组成。这告诉另一端将资源与该标识(ID)关联起来,并在连接结束时无限期地保存它们。

标识(ID)不应该以0字节开始,这是为通信端(peer)内部使用保留的。peer可能拒绝身份标识,应该对无限期持有资源的代价保持谨慎。

下面的ABNF语法定义了任意方向的ZMTP连接:

connection  = greeting content
greeting    = anonymous / identity
anonymous   = %x01 idflags
identity    = length idflags (%x01-ff) *OCTET
idflags     = %00

标识帧的标志字段(idflags)不应该被验证,应该被设置为零。

内容层

序言

通过连接发送的ZMTP内容消息的格式和语义取决于该连接方向的内容类型,这在协议中没有指定,但必须由通信端(peer)承担。

以下ABNF语法定义了ZMTP内容:

content     = *broadcast / *addressed / *neutral

广播内容(Broadcast Content)

广播内容用于发布者和订阅者之间。发布者应当发送广播内容。订阅者不得发送任何内容。

以下ABNF语法定义了ZMTP广播内容:

broadcast   = message

接收者可以过滤消息。可以使用任何匹配机制(前缀、通配符、regexp)。ZMTP没有对此进行标准化,尽管当前的ZeroMQ实现使用前缀匹配。

寻址内容(Addressed Content)

寻址内容在请求-应答链中的端点之间使用。在请求-应答链中,任何端点都可以向任何其他端点发送寻址内容。

以下ABNF语法定义了ZMTP寻址内容:

addressed   = envelope message
envelope    = *more-frame delimiter
delimiter   = %x01 more

同行应按下列方式使用信封(envelope):

  • 当一个对端向另一个对端发送请求时,它应该发送一个至少包含分隔符的信封。
  • 当一个对端将一个请求从一个对端转发给另一个对端时,它应该将原始发送对端的标识放在信封前面(作为标识帧)。
  • 当对端接受请求并以答复进行响应时,它应该展开并保存直到并包括分隔符的完整地址信封,然后将剩余的消息传递给应用程序,然后用直到并包括分隔符的完整地址信封重新包装应用程序的响应。

通过这种方式,对端链可以在转发请求时将地址推送到信封上,并从信封上弹出地址以返回应答。

中性的内容

中性内容用于不需要路由的对端之间。任何一个对端都可以向另一个对端发送中性的内容,尽管特定的对端实现可以忽略来自其对端的内容。

以下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没有尝试安全性,而应用程序可以在其上添加一层。

你可能感兴趣的:(Linux,数据库,服务器,网络)