STOMP 协议规范,版本 1.2
- 摘要
- 概览
- 背景
- 协议概览
- 协议变更
- 设计哲学
- 一致性
- STOMP帧
- 值的编码
- 消息Body
- 标准的Headers
- Header content-length
- Header content-type
- Header receipt
- 重复的Header Entries
- 消息大小限制
- 连接延迟关闭
- Connecting
- CONNECT或STOMP帧
- CONNECTED帧
- 协议协商
- 心跳
- 客户端可发送的帧
- SEND
- SUBSCRIBE
- SUBSCRIBE id Header
- SUBSCRIBE ack Header
- UNSUSCRIBE
- ACK
- NACK
- BEGIN
- COMMIT
- ABORT
- DISCONNECT
- 服务器可发送的帧
- MESSAGE
- RECEIPT
- ERROR
- 帧对应的Headers
- 扩展的BNF
- 许可
摘要
STOMP 是一个简单的可互操作协议,设计用于异步消息传递,通过中介服务器在客户端之间进行。它定义了客户端和服务器之间传递消息的基于文本的线路格式。
STOMP 已经活跃使用多年,并且被许多消息代理和客户端库支持。本规范定义了 STOMP 1.2 协议,并且是 STOMP 1.1 的更新。 请将反馈发送至stomp-spec@googlegroups.com邮件列表。
概览
背景
STOMP 起源于从 Ruby、Python 和 Perl 等脚本语言连接到企业消息代理的需求。在这样的环境中,通常执行的逻辑上简单的操作,如“可靠地发送单个消息并断开连接”或“消费给定目的地的所有消息”。
它是一种替代其他开放消息协议的选择,比如AMQP以及在JMS代理中使用的特定实现的线路协议,例如OpenWire。它通过覆盖一小部分常用的消息操作来区分自己,而不是提供全面的通信API。
复制再试一次分享
最近,STOMP已经成为一种成熟的协议,它可以用于这些简单用例之外的场合,因为它现在提供了wire-level特性,但仍然保持了其核心的设计原则,即简单性和互操作性。
协议概览
STOMP 是一个基于帧的协议,它的帧结构模仿了 HTTP。一个帧由命令、一组可选header和一个可选body组成。STOMP 是基于文本的,但也允许传输二进制消息。STOMP 的默认编码是 UTF-8,但它支持为消息主体指定备用编码。
STOMP 服务器被建模为一组destinations,消息可以发送到这些destinations。STOMP 协议将没有规定destination字符串的格式和内容,它们的语法与使用的服务器相关。此外,STOMP 没有定义destination的传递语义应该是什么。destination的传递,或“消息交换”语义,在不同服务器可以不同,甚至不同destination间也可以不同。这使得服务器能够更有创造性地使用 STOMP 支持的语义。
STOMP 客户端是一个用户代理,可以以两种(可能同时)模式运行:
- 作为生产者,通过一个
SEND
帧向服务器上的destination发送消息。 - 作为消费者,向给定的destination发送
SUBSCRIBE
帧,并从服务器接收作为MESSAGE
帧的消息。
协议变更
STOMP 1.2 与 STOMP 1.1 大体上向后兼容。只有两个不兼容的变更:
- 现在可以使用回车加换行符来代替换行符结束帧行。
- 消息确认已经被简化,现在使用专门的header。
除了这些,STOMP 1.2 没有引入新特性,而是专注于阐明规范的某些领域,如:
- 重复的帧header entries
content-length
和content-type
headers的使用- 服务器必须支持
STOMP
帧 - 连接延迟关闭
- 订阅和事务标识符的范围和唯一性
RECEIPT
帧相对于先前帧的含义
设计哲学
驱动 STOMP 设计的主要哲学是简单性和互操作性。
STOMP 被设计为一个轻量级协议,易于在大多数编程语言上同时实现客户端和服务器端的功能。这意味着,特别是对服务器架构没有太多限制,许多特性如destination命名和可靠性语义是特定于实现的。
在本规范中,我们将注意 STOMP 1.2 未明确定义的服务器功能。你应该查阅对应的STOMP 服务器的文档,了解这些功能的具体实现细节。
一致性
本文档中的关键词MUST”, “MUST NOT”, “REQUIRED”, “SHALL”, “SHALL NOT”, “SHOULD”, “SHOULD NOT”, “RECOMMENDED”, “MAY”和“OPTIONAL”应按照 R**RFC 2119** 中的描述进行解释。
实现可能会对不受约束的输入施加特定于实现的限制,例如,防止拒绝服务攻击、防止内存不足或解决特定于平台的限制。
本规范定义的一致性类别是 STOMP 客户端和 STOMP 服务器。
STOMP 的帧
STOMP 是一个基于帧的协议,它假设底层有一个可靠的双向流网络协议(如 TCP)。客户端和服务器将使用通过流发送的 STOMP 帧进行通信。一个帧的结构如下所示:
COMMAND
header1:value1
header2:value2
Body^@
帧以一个命令字符串开始,命令字符串紧接着结束行(EOL)表示命令行终止。EOL 由一个可选的回车(octet 13)后面跟着一个必需的换行(octet 10)组成。在命令之后是零个或多个以 <key>:<value>
格式的header内容。每个header都以 EOL 终止。一个空行(即额外的 EOL)表示headers的结束和body内容的开始。然后,body后面跟着 NULL octet。本文档中的示例将使用可视化字符 ^@表示,ASCII 中是用control-@ 来表示 NULL octet。NULL octet后面可以跟着多个 EOL。有关如何解析 STOMP 帧的更多详细信息,请参见本文档的“扩展的 BNF”部分。
本文档中引用的所有命令和header名称都是区分大小写的。
值编码
命令和headers使用 UTF-8 编码。除了 CONNECT
和 CONNECTED
帧之外的所有帧,还将转义 UTF-8 编码的headers中发现的任何回车、换行或冒号。
转义是必要的,以允许header键和值包含那些作为值的帧header分隔octet。为了与 STOMP 1.0 保持向后兼容,CONNECT 和 CONNECTED 帧不转义回车、换行或冒号octet。
C 风格字符串文字转义用于编码在 UTF-8 已编码的headers中发现的任何回车、换行或冒号。在解码帧headers时,必须应用以下转换:
\\r
(octet 92 and 114) 转换为回车 (octet 13)\\n
(octet 92 and 110) t转换为换行 (octet 10)\\c
(octet 92 and 99) 转换为:
(octet 58)\\\\
(octet 92 and 92) 转换为\\
(octet 92)
未定义的转义序列,如 \t (octet 92 和 116) 必须被视为致命的协议错误。反之,在编码帧headers时,必须应用反向转换。
STOMP 1.0 规范包括了许多带有headers填充的示例帧,许多服务器和客户端被实现为修剪或填充headers值。如果应用程序想要发送不应该被修剪的header,则这会引起问题。在 STOMP 1.2 中,客户端和服务器绝不能使用删掉headers的空格或往headers填充空格。
消息的主体
只有 SEND
, MESSAGE
, 和 ERROR
帧可能有主体。所有其他帧必须没有主体。
标准的Headers
一些headers可能被使用,并且在大多数帧中具有特殊含义。
Header content-length
所有帧都可能包含 content-length
头部。这个header是消息body长度的字节数量。如果包含了 content-length
header,就必须读取这么长的字节,不管body中是否有 NULL octets。帧的终止符仍然是用 NULL octets。
如果帧包含body,SEND
、MESSAGE
和 ERROR
帧应包括一个 content-length
header以简化帧的解析。如果帧的body包含 NULL octets,帧必须包括一个 content-length
header。
Header content-type
如果帧包含body,SEND
、MESSAGE
和 ERROR
帧应包括一个 content-type
header以帮助接收方解释其body。如果设置了 content-type
header,它的值必须是描述body格式的 MIME 类型。否则,接收方应将body视为二进制数据块。
以 text/
开头的 MIME 类型的默认文本编码是 UTF-8。如果要使用不同编码的文本 MIME 类型,则应将;charset=<encoding>
附加到 MIME 类型。例如,如果要发送 UTF-16 编码的 HTML body,则应使用 text/html;charset=utf-16
。;charset=<encoding>
还应被追加到任何可以被解释为文本的非 text/ MIME 类型。比如 UTF-8 编码的 XML。它的content-type
应设置为 application/xml;charset=utf-8
。
所有 STOMP 的客户端和服务器必须支持 UTF-8 编码和解码。因此,为了在异构计算环境中实现最大的互操作性,建议使用 UTF-8 对基于文本的内容进行编码。
Header receipt
除了 CONNECT
之外的任何客户端帧都可能指定一个带有任意值的 receipt
header。这将让服务器返回一个 RECEIPT
帧给客户端,表示已处理完成客户端发来的帧(有关更多详细信息,请参见 RECEIPT 帧)。
SEND
destination:/queue/a
receipt:message-12345
hello queue a^@
重复的Header Entries
由于消息系统可以像 SMTP 一样以存储和转发拓扑结构进行组织,因此一条消息在到达消费者之前可能会经过多个消息服务器。STOMP 服务器可以通过在消息中添加headers或修改现有header来“更新”header值。
如果客户端或服务器接收到重复的帧header entries,应只使用第一个header entry作为头部条目的值。后续值仅用于维护头部状态更改的历史记录,并且可以被忽略。
例如,如果客户端接收到这样的消息:
MESSAGE
foo:World
foo:Hello
^@
foo
header的值是 World。
大小限制
为了防止恶意客户端利用服务器的内存分配机制,服务器可能对以下内容设置最大限制:
- 单个帧中允许的headers数量
- header行的最大长度
- 帧body的最大大小
如果超过这些限制,服务器应该向客户端发送一个 ERROR
帧,然后关闭连接。
连接延迟关闭
STOMP 服务器必须能够支持客户端的快速连接和断开。
这意味着服务器可能只允许已关闭的连接,在连接重置之前保留很短的时间。
因此,客户端可能在套接字被重置之前,无法正常接收服务器发送的最后一个帧(例如响应 DISCONNECT
帧的 ERROR
帧或 RECEIPT
帧)。
Connecting
STOMP 客户端通过发送 CONNECT
帧来启动到服务器的stream或 TCP 连接:
CONNECT
accept-version:1.2
host:stomp.github.org
^@
如果服务器接受连接尝试,它将响应 CONNECTED
帧:
CONNECTED
version:1.2
^@
服务器可以拒绝任何连接尝试。服务器应响应一个 ERROR
帧,解释拒绝连接的原因,然后关闭该连接。
CONNECT or STOMP 帧
STOMP
的服务器处理STOMP
帧的方式和处理 CONNECT
帧相同。STOMP 1.2 版本的客户端应继续支持 CONNECT
命令来保持与 STOMP 1.0 版本服务器的向后兼容性。
客户端连接STOMP 1.2 服务器(以及一些 STOMP 1.1 服务器)能使用 STOMP
帧来代替 CONNECT
帧,优点是协议嗅探器/鉴别器将能够将 STOMP 连接与 HTTP 连接区分开来。
STOMP 1.2 客户端必须设置以下headers:
accept-version
: 客户端支持的 STOMP 协议版本。有关协议协商的更多详细信息,请参阅协议协商。host
:客户端希望连接的虚拟主机的名称。建议客户端将这个值设置为建立套接字的主机名,或者其他任意名称。如果这个header不匹配已有的虚拟主机,支持虚拟托管的服务器可以选择一个默认虚拟主机或拒绝连接。
STOMP 1.2 客户端可选的headers:
login
: 有安全要求的 STOMP 服务器进行身份验证的用户标识符。passcode
: 有安全要求的 STOMP 服务器进行身份验证的密码。heart-beat
: 心跳设置。
CONNECTED 帧
STOMP 1.2 服务器必须设置以下headers:
version
: 会话将使用的 STOMP 协议版本。有关更多详细信息,请参阅协议协商。
STOMP 1.2 服务器可选的headers:
-
heart-beat
: 心跳设置。 -
session
: 用于标识会话的唯一会话标识符。 -
server
: 包含有关 STOMP 服务器信息的字段。该字段必须包含server-name字段,并且后面可以是由空格octet分隔的可选注释字段。server-name 字段由一个名称标记和一个可选的版本号标记组成。
server = name ["/" version] *(comment)
例如:
server:Apache/1.3.9
协议协商
从 STOMP 1.1 及以后,CONNECT
帧必须包含 accept-version
header。它应设置为客户端支持的STOMP 协议版本的集合(集合里的版本号用逗号分隔,并且随版本号数值递增)。如果缺少 accept-version
header,则意味着客户端仅支持 1.0 版本的协议。
后面的会话将使用客户端和服务器之间共同支持的协议的最高版本。
例如,如果客户端发送以下消息:
CONNECT
accept-version:1.0,1.1,2.0
host:stomp.github.org
^@
服务器将响应用它与客户端支持的最高版本:
CONNECTED
version:1.1
^@
如果客户端和服务器没有共同支持的协议版本,那么服务器必须响应类似示例里的ERROR
帧,然后关闭连接:
ERROR
version:1.2,2.1
content-type:text/plain
Supported protocol versions are 1.2 2.1^@
心跳机制
可以选择使用心跳机制来测试底层 TCP 连接的健康状况,并确保远端处于活动状态。
为了启用心跳机制,双方都必须声明它能够做什么以及它希望对方做什么。这发生在 STOMP 会话的一开始,通过向 CONNECT
和 CONNECTED
帧添加一个 heart-beat
header。
当使用心跳机制时,heart-beat
header必须包含两个由逗号分隔的正整数。
第一个数字表示发送方能够做的事情(传出心跳):
- 0 表示它不能发送心跳
- 否则,表示可以保证发送心跳间隔的最小毫秒数
第二个数字表示发送方想要得到的(传入心跳):
- 0 表示它不想接收心跳
- 否则,它表示心跳之间所需的毫秒数
heart-beat
header是可选的。缺少的 heart-beat
header必须被视为与“heart-beat:0,0”header相同,即:该方不能发送也不想接收到心跳。
heart-beat
header提供了足够的信息,以便各方可以找出是否可以使用心跳,心跳的方向以及频率。
更具体地说,初始帧看起来像这样的格式:
CONNECT
heart-beat:<cx>,<cy>
CONNECTED
heart-beat:<sx>,<sy>
对于客户端发给服务器的心跳:
- 如果 <cx> 是 0(客户端不能发送心跳)或 <sy> 是 0(服务器不想接收心跳),那么就没有心跳
- 否则,每 MAX(<cx>,<sy>) 毫秒会有心跳
在另一个方向上(服务器给客户端发送心跳),<sx>
和 <cy>
以相同的方式使用。
关于心跳本身,通过网络连接接收到的任何新数据都是远端活动的迹象。在给定方向上,如果心跳每 <n>
毫秒预期一次:
- 发送方必须至少每
<n>
毫秒发送一次新数据到网络连接 - 如果发送方没有真实的 STOMP 帧要发送,它必须发送一个结束行(EOL)
- 如果,在至少
<n>
毫秒的时间窗口内,接收方没有接收到任何新数据,它可能会认为连接已死亡 - 由于计时不准确,接收方应该容忍并考虑误差范围
客户端发送的帧
客户端可以发送不在本列表中的帧,但对于这样的帧,STOMP 1.2 服务器可能会响应一个ERROR
帧,然后关闭连接。
[SEND](<https://stomp.github.io/stomp-specification-1.2.html#SEND>)
[SUBSCRIBE](<https://stomp.github.io/stomp-specification-1.2.html#SUBSCRIBE>)
[UNSUBSCRIBE](<https://stomp.github.io/stomp-specification-1.2.html#UNSUBSCRIBE>)
[BEGIN](<https://stomp.github.io/stomp-specification-1.2.html#BEGIN>)
[COMMIT](<https://stomp.github.io/stomp-specification-1.2.html#COMMIT>)
[ABORT](<https://stomp.github.io/stomp-specification-1.2.html#ABORT>)
[ACK](<https://stomp.github.io/stomp-specification-1.2.html#ACK>)
[NACK](<https://stomp.github.io/stomp-specification-1.2.html#NACK>)
[DISCONNECT](<https://stomp.github.io/stomp-specification-1.2.html#DISCONNECT>)
SEND
SEND
帧向消息系统中的destination发送消息。它有一个必需的destination
header,指示消息发送的目的地。SEND
帧的body是要发送的消息内容。例如:
SEND
destination:/queue/a
content-type:text/plain
hello queue a
^@
这给消息值为/queue/a
的destination发送了一条消息。请注意,STOMP协议 将这个destination值视为一个普通的字符串,不会假设它会传递任何语义。你应查阅你的 STOMP 服务器的文档,来找出如何构造一个destination名称,该名称为你提供应用程序所需的传递语义。
消息的可靠性语义也是特定服务器相关,并且取决于所使用的destination值和其他消息headers,例如transaction
header或其他服务器特定的消息headers。
SEND
支持一个transaction
header,允许事务性发送消息。
如果存在body,SEND
帧应包括一个 [content-length](<https://stomp.github.io/stomp-specification-1.2.html#Header_content-length>)
header和一个**[content-type](<https://stomp.github.io/stomp-specification-1.2.html#Header_content-type>)
** header。
应用程序可以向 SEND
帧添加任意用户定义的headers。用户定义的headers通常用于允许消费者基于 SUBSCRIBE
帧上的选择器使用应用程序定义的headers来过滤消息。用户定义的headers必须在 MESSAGE
帧中传递。
如果服务器由于任何原因无法成功处理 SEND
帧,服务器必须向客户端发送一个 ERROR
帧,然后关闭连接。
SUBSCRIBE
SUBSCRIBE
帧用于注册给定destination的监听。像 SEND
帧一样,SUBSCRIBE
帧需要一个 destination
header,表示客户端想要订阅的destination。此后,在订阅destination上收到的任何消息都将作为 MESSAGE
帧从服务器传递到客户端。 ack
header用于控制消息的确认模式。
示例:
SUBSCRIBE
id:0
destination:/queue/foo
ack:client
^@
如果服务器无法成功创建订阅,服务器必须向客户端发送一个 ERROR
帧,然后关闭连接。
STOMP 服务器可以支持附加的服务器特定headers来自定义订阅的传递语义。有关详细信息,请参阅服务器的文档。
SUBSCRIBE id Header
由于单个连接可以与服务器有多个打开的订阅,因此必须在帧中包含一个 id 头部,以唯一标识订阅。id 头部允许客户端和服务器将后续的 MESSAGE 或 UNSUBSCRIBE 帧与原始订阅关联起来。
由于单个连接可以与服务器打开多个订阅,因此帧中必须包含 id
header 用以唯一标识一个订阅。 id
header 允许客户端和服务器将后续的 MESSAGE
或 UNSUBSCRIBE
帧与原始订阅关联起来。
在同一连接内,不同的订阅必须使用不同的订阅标识符。
SUBSCRIBE ack Header
ack
header的可选值有 auto
、client
或 client-individual
。如果该值未设置,默认为 auto
。
当 ack
模式是 auto
时,客户端不需要在它接收到的消息后,向服务器发送 ACK
帧。一旦服务器将消息发送给客户端,服务器就会认为客户端已收到消息。这种确认模式可能会导致传输到客户端的消息被丢弃。
当 ack
模式为 client
时,客户端必须为它处理过消息,向服务器发送 ACK
帧。如果连接在客户端发送 ACK
帧之前失败,服务器将假定消息尚未被处理,并且可能会将消息重新传递给另一个客户端。客户端发送的 ACK
帧将被视为累积确认。这意味着确认操作适用于 ACK
帧中指定的消息,以及在 ACK
'ed 消息之前发送到订阅的所有消息。
如果客户端没有处理某些消息,它应发送 NACK
帧来告诉服务器它没有消费这些消息。
当 ack
模式为 client-individual
时,确认操作就像 client
确认模式一样,只是客户端发送的 ACK
或 NACK
帧不是累积的。这意味着对后续消息的 ACK
或 NACK
帧不应导致之前的消息被确认。
UNSUBSCRIBE
UNSUBSCRIBE
帧用于删除现有的订阅。一旦订阅被删除,STOMP 连接将不再从该订阅接收消息。
由于单个连接可以与服务器有多个打开的订阅,因此必须在帧中包含一个 id
header ,用来唯一标识要删除的订阅。这个header的值必须和已订阅的订阅标识符匹配。
示例:
UNSUBSCRIBE
id:0
^@
ACK
ACK
是client
或 client-individual
确认模式下,用于确认消费的消息。从这样的订阅通道接收到的任何的消息,在通过 ACK
确认之前都不会被认为已被消费。
ACK
帧必须包括一个与被确认的 MESSAGE
的 ack
header匹配的 id
header。可选地,可以指定一个transaction
header,表示消息确认是当前事务的一部分。
ACK
id:12345
transaction:tx1
^@
NACK
NACK
与 ACK
相反。它用于告诉服务器客户端没有消费消息。服务器随后可以将消息发送给其他的客户端、丢弃它,或者将它放入死信队列。具体的行为是特定服务器有关的。
NACK
使用与 ACK
相同的headers:id
(必需)和 transaction
(可选)。
如果订阅的 ack
模式是 client-individual
,则 NACK
适用于单个消息。如果订阅的 ack
模式是 client
,则适用于所有在未被 ACK
'ed 或 NACK
'ed 确认之前发送的消息。
BEGIN
BEGIN
用于开启一个事务。在这种情况下,事务适用于发送和确认 - 在事务期间发送或确认的任何消息将根据事务以原子方式处理。
BEGIN
transaction:tx1
^@
transaction
header是必填的,事务标识符将用于 SEND
、COMMIT
、ABORT
、ACK
和 NACK
帧,将它们绑定到相同名称的事务上。在同一连接内,不同的事务必须使用不同的事务标识符。
如果客户端发送了 DISCONNECT
帧,或者 TCP 连接由于任何原因失败,任何未提交的开始事务将被隐式中止。
COMMIT
COMMIT
用于提交正在进行的事务。
COMMIT
transaction:tx1
^@
transaction
heade是必填的,并且必须指定要提交的事务的标识符。
ABORT
ABORT
用于回滚正在进行的事务。
ABORT
transaction:tx1
^@
transaction
heade是必填的,并且必须指定要中止的事务的标识符。
DISCONNECT
客户端可以随时通过关闭套接字与服务器断开连接,但不能保证先前发送的帧已被服务器接收。要进行优雅地关闭,客户端可以确保所有先前发送的帧都已被服务器接收,客户端应该:
- 发送一个带有设置了
receipt
header的DISCONNECT
帧。示例:
DISCONNECT
receipt:77
^@
-
等待
DISCONNECT
响应的RECEIPT
帧。示例:RECEIPT receipt-id:77 ^@
-
关闭套接字。
请注意,如果服务器关闭它的套接字太快了,客户端可能永远收不到期望的 RECEIPT
帧。有关更多信息,请参见“连接挂起”部分。
在发送 DISCONNECT
帧后,客户端绝不能发送其他的帧。
服务端发送的帧
有时,服务器会向客户端发送帧(除了初始的 CONNECTED 帧之外)。这些帧可能是以下之一:
[MESSAGE](<https://stomp.github.io/stomp-specification-1.2.html#MESSAGE>)
[RECEIPT](<https://stomp.github.io/stomp-specification-1.2.html#RECEIPT>)
[ERROR](<https://stomp.github.io/stomp-specification-1.2.html#ERROR>)
MESSAGE
MESSAGE
帧用于将订阅中的消息传递给客户端。
MESSAGE
帧必须包括一个 destination
header,指示消息发送到的目的地。如果消息是使用 STOMP 发送的,那么这个 destination
header 应该是与相应 SEND
帧中使用的destination
header相同。
MESSAGE
帧还必须包含一个 message-id
header,该header具有该消息的唯一标识符,以及一个与接收该消息的订阅的标识符相匹配的subscription
header。
如果消息是从需要显式确认(ack是 client
或 client-individual
模式)的订阅中接收的,那么 MESSAGE
帧还必须包含一个 ack
header,该header可以是任意值。这个header将用于将消息与后续的 ACK
或 NACK
帧关联。
帧体包含消息的内容如下:
MESSAGE
subscription:0
message-id:007
destination:/queue/a
content-type:text/plain
hello queue a^@
如果消息包含body,MESSAGE
帧应包括一个 [content-length](<https://stomp.github.io/stomp-specification-1.2.html#Header_content-length>)
header和一个 [content-type](<https://stomp.github.io/stomp-specification-1.2.html#Header_content-type>)
header。
除了添加和特定服务器相关的header之外,MESSAGE
帧还将包含消息发送到目的地时,包含的所有用户定义的标头。
请查阅你使用的服务器的文档,了解它向消息额外添加的headers。
RECEIPT
RECEIPT
帧是服务器在成功处理要求返回收据的客户端帧后,发送给客户端的消息。RECEIPT
帧必须包括一个receipt-id
header,其中该值是作为收据的帧中的receipt
header的值。
RECEIPT
receipt-id:message-12345
^@
RECEIPT
帧是对相应客户端帧已由服务器处理完毕的确认消息。由于 STOMP 是基于流的,因此收据也是服务器已接收到所有先前帧的累积确认。但是,这些先前的帧可能尚未完全处理。如果客户端断开连接,先前接收到的帧应该继续由服务器处理。
ERROR
如果出现问题,服务器可能会发送 ERROR
帧。在这种情况下,它必须在发送 ERROR
帧后立即关闭连接。参考下一节有关连接挂起。
ERROR
帧应包含一个 message
header来简要描述错误原因,并且body 里可以包含更详细的信息(或者也可以为空)。
ERROR
receipt-id:message-12345
content-type:text/plain
content-length:170
message:malformed frame received
The message:
-----
MESSAGE
destined:/queue/a
receipt:message-12345
Hello queue a!
-----
Did not contain a destination header, which is REQUIRED
for message propagation.
^@
如果错误的发生与客户端发送的某个帧有关,服务器应在 ERROR
帧中添加额外的headers,来帮助客户端识别引起错误的原始帧。例如,如果该帧包含了一个 receipt
header,ERROR
帧应将 receipt-id
header设置为成引起错误帧的 receipt
header 一样的值。
如果消息包含body,ERROR
帧应包括一个 [content-length](<https://stomp.github.io/stomp-specification-1.2.html#Header_content-length>)
header和一个 [content-type](<https://stomp.github.io/stomp-specification-1.2.html#Header_content-type>)
header。
Frames and Headers
除了上面描述的标准头部(content-length
、content-type
和 receipt
),这里是本规范中定义的每个帧对应的必须或可选的头部:
CONNECT
或STOMP
- 必填:
accept-version
,host
- 可选:
login
,passcode
,heart-beat
- 必填:
CONNECTED
- 必填:
version
- 可选:
session
,server
,heart-beat
- 必填:
SEND
- 必填:
destination
- 可选:
transaction
- 必填:
SUBSCRIBE
- 必填:
destination
,id
- OPTIONAL:
ack
- 必填:
UNSUBSCRIBE
- 必填:
id
- 可选: none
- 必填:
ACK
orNACK
- 必填:
id
- 可选:
transaction
- 必填:
BEGIN
或COMMIT
或ABORT
- REQUIRED:
transaction
- 可选: none
- REQUIRED:
DISCONNECT
- 必填: none
- 可选:
receipt
MESSAGE
- 必填:
destination
,message-id
,subscription
- 可选:
ack
- 必填:
RECEIPT
- 必填:
receipt-id
- 可选: none
- 必填:
ERROR
- 必填: none
- 可选:
message
此外,SEND
和 MESSAGE
帧可能包含用户自定义的headers,这些headers应被视为消息的一部分。此外,ERROR
帧应包括额外的headers,来帮助客户端识别引起错误的原始帧。
最后,STOMP 服务器可以使用额外的headers来提供对持久性或过期等功能的访问。有关详细信息,请参阅服务器的文档。
扩展的 BNF
STOMP 会话可以使用 HTTP/1.1 RFC 2616 中使用的Backus-Naur Form(BNF)语法进行更正式的描述。
NULL = <US-ASCII null (octet 0)>
LF = <US-ASCII line feed (aka newline) (octet 10)>
CR = <US-ASCII carriage return (octet 13)>
EOL = [CR] LF
OCTET = <any 8-bit sequence of data>
frame-stream = 1*frame
frame = command EOL
*( header EOL )
EOL
*OCTET
NULL
*( EOL )
command = client-command | server-command
client-command = "SEND"
| "SUBSCRIBE"
| "UNSUBSCRIBE"
| "BEGIN"
| "COMMIT"
| "ABORT"
| "ACK"
| "NACK"
| "DISCONNECT"
| "CONNECT"
| "STOMP"
server-command = "CONNECTED"
| "MESSAGE"
| "RECEIPT"
| "ERROR"
header = header-name ":" header-value
header-name = 1*<any OCTET except CR or LF or ":">
header-value = *<any OCTET except CR or LF or ":">
License
本规范根据 Creative Commons Attribution v3.0 许可协议授权。