一、简介Abstract
STOMP is a simple interoperable protocol designed for asynchronous message passing between clients via mediating servers. It defines a text based wire-format for messages passed between these clients and servers.
- STOMP是专为实现客户端之间(通过中间服务器) 异步通信的一个简单通信协议
- 基于文本的消息格式
二、背景
1.STOMP arose from a need to connect to enterprise message brokers from scripting languages such as Ruby, Python and Perl.
需要脚本实现企业消息服务的环境下诞生。
2.It is an alternative to other open messaging protocols such as AMQP and implementation specific wire protocols used in JMS brokers such as OpenWire.
其他消息的替代方案如AMQP 与 OpenWire
三、协议概要
- Stomp类似HTTP协议是一个基于数据帧的协议。
一个数据帧由 命令行 + 报头(optional) + 正文(optional) - STOMP是基于文本的,但也允许二进制消息的传输。 STOMP的默认编码为UTF-8,支持为消息体指定其他编码。
3.1 Stomp服务器
(1). STOMP服务器被建模为可以向其发送消息的一组目的destinations。
(2). Additionally STOMP does not define what the delivery semantics of destinations should be. The delivery, or “message exchange”, semantics of destinations can vary from **server to server **and even from destination to destination. This allows servers to be creative with the semantics that they can support with STOMP.
3.2 Stomp客户端
两个角色:
- as a producer, sending messages to a destination on the server via a SEND frame。
- as a consumer, sending a SUBSCRIBE frame for a given destination and receiving messages from the server as MESSAGE frames.
3.3 Stomp数据帧Frame
Stomp 是一个基于数据帧的通信协议,它的下层是可靠的Tcp协议。
一个数据帧由 命令行 + 报头(optional) + 正文(optional)组成
一个标准的数据帧像下面这样
COMMAND
header1:value1
header2:value2
Body^@
详细:
1.command + EOL结束换行符
//zero or more header entries in <key>:<value> format
2.一个或者多个(键值对+EOL)组成的报头
3.空行或者EOL代表报头的结束
4.Body
3.4 编码
1.The commands and headers are encoded in UTF-8
2.除了CONNECT CONNECTED
回车符
换行符
冒号
帧外其他的帧都会对这些符号进行转意处理,CONNECT CONNECTED没有是因为为了兼容Stomp 1.0以下版本。
\r (octet 92 and 114) translates to carriage return (octet 13)
\n (octet 92 and 110) translates to line feed (octet 10)
\c (octet 92 and 99) translates to : (octet 58)
\\ (octet 92 and 92) translates to \ (octet 92)
3.5 Body
Only the SEND, MESSAGE, and ERROR frames MAY have a body. All other frames MUST NOT have a body.
3.6 Standard Headers
常用的一些报头
|报头|说明|
|----|----|----|
|content-length|消息正文的长度|
|content-type|MUST be a MIME type which describes the format of the body 正文格式|
防止恶意的内存攻击,服务端应该:
the number of frame headers allowed in a single frame
the maximum length of header lines
the maximum size of a frame body
3.7重复的报头
Since messaging systems can be organized in store and forward topologies, similar to SMTP, a message may traverse several messaging servers before reaching a consumer.
1. A STOMP server MAY 'update' header values by either prepending headers to the message or modifying a header in-place in the message.
2. If a client or a server receives repeated frame header entries, only the first header entry SHOULD be used as the value of header entry. Subsequent values are only used to maintain a history of state changes of the header and MAY be ignored.
For example, if the client receives:
MESSAGE
foo:World
foo:Hello
^@
The value of the foo header is just World.
3.8 客户端与服务端Connect连接
客户端发出CONNECT frame 请求
CONNECT
accept-version:1.2
host:stomp.github.org
^@
连接成功服务端会返回 a CONNECTED frame:
CONNECTED
version:1.2
^@
如过连接被拒绝服务端将会返回 an ERROR frame 告诉客户端被拒绝的原因,然后关闭连接。
3.8.1 Stomp 与 Connect
- STOMP 1.2客户端应该继续使用CONNECT命令保持与STOMP 1.0服务器的向后兼容性。
- 使用STOMP帧而不是CONNECT帧的客户端将只能连接到STOMP 1.2服务器(以及一些STOMP 1.1服务器),但优点是协议嗅探器/鉴别器能够区分STOMP连接和HTTP连接。
STOMP 1.2客户端必须设置以下头:
|报头|说明|建议|
|---|---|---|---|
|accept-version|客户端支持的STOMP协议的版本。||
|host|客户端希望连接的虚拟主机的名称。|建议将host设置为提供服务的主机名或者是服务端定的虚拟主机的名字。如果host字段与已知的虚拟主机不匹配,则支持虚拟主机的服务器会选择默认虚拟主机或会拒绝客户端的连接。实际使用中,服务端笔者用的是rabbitMq服务器,如果host名称不对,会直接拒绝客户的连接。|
附rabbitMq 虚拟主机的设置方法与设置权限的方法:
STOMP 1.2客户端可以设置以下标题:
报头 | 说明 |
---|---|
login | 登录名 |
passcode | 密码 |
heart-beat | 心跳设置 |
3.8.2 服务端CONNECTED
STOMP 1.2服务器必须设置以下头:
报头 | 说明 |
---|---|
version | The version of the STOMP protocol the session will be using |
heart-beat | The Heart-beating settings. |
session | A session identifier that uniquely identifies the session. |
server | Stomp服务器信息 |
3.8.3 session使用的协议版本
从STOMP 1.1开始,CONNECT帧必须包含accept-version头。
它应该设置为客户端支持的STOMP协议版本递增顺序,不同的版本间以逗号分隔。
CONNECT
accept-version:1.0,1.1,2.0
host:stomp.github.org
^@
服务端将会返回服务端与客户端同时支持的Stmop版本的最高版本。
如:
CONNECTED
version:1.1
^@
如过客户端和服务端之间没有共同的Stomp协议版本,服务端将会返回ERROR Frame :
ERROR
version:1.2,2.1
content-type:text/plain
Supported protocol versions are 1.2 2.1^@
3.9 Heart-beating 心跳数据
心跳数据是为了测试底层的TCP协议是否可用,以及远端服务器是否运作正常,是否和服务器保持着连接。
格式:
heart-beat:正整数,正整数
第一个数值表示发送者可以输出的心跳
0 代表发送者不能输出心跳数据
num 发送者能保证输出心跳数据的最小间隔(ms为单位)
第二个数字则表示发送者想要获得的(传入心跳):
0 表示不想接收心跳
num 所需的心跳数据间隔(ms为单位)
CONNECT
heart-beat:<cx>,<cy>
CONNECTED:
heart-beat:<sx>,<sy>
对于服务端来说:
1.如果 <cx>,<sy> 等于0,客户端不能发送心跳数据,服务端不必接收心跳数据的情况。服务端返回的CONNECTED帧中将不会返回heart-beat字段。
2. 否则的话,心跳数据的频率将会以<cx>,<sy>两者中最大的那一个值输出。
心跳频率确定好后,假如是<n>ms每次的心跳频率那么:
- 发送者必须在<n>ms内发送一次新的心跳数据。
- 如果发送方没有要发送的实际STOMP帧, it MUST send an end-of-line (EOL)
- 如果在至少<n>毫秒的时间窗口内,接收器没有接收到任何新数据,则其可以认为连接为死
- 由于定时不准确,接收机应该容忍并考虑误差容限
4 客户端以及服务端使用的Frame帧
客户端:
报头 | 格式 | 说明 | |
---|---|---|---|
SEND |
服务端: