STOMP协议规范--转载
原文地址:http://simlegate.com/2013/10/17/stomp-specification-1.2/
摘要
STOMP是一個(gè)簡(jiǎn)單的可互操作的協(xié)議, 被用于通過(guò)中間服務(wù)器在客戶端之間進(jìn)行異步消息傳遞。它定義了一種在客戶端與服務(wù)端進(jìn)行消息傳遞的文本格式.
STOMP已經(jīng)被使用了很多年,并且支持很多消息brokers和客戶端庫(kù)。這個(gè)規(guī)范定義STOMP?1.2協(xié)議以及對(duì)1.1版本的更新。
發(fā)送反饋到stomp-spec@googlegroups.com.
概述
背景
由于需要用腳本語(yǔ)言如Ruby,?Python,?Perl去連接企業(yè)級(jí)的消息brokers, STOMP產(chǎn)生了.在這種情況下,STMOP實(shí)現(xiàn)了一些簡(jiǎn)單的操作,比如可靠地發(fā)送單一的消息,然后斷開(kāi)或者從目的地消費(fèi)所有消息。
STOMP是除AMQP開(kāi)放消息協(xié)議之外地另外一個(gè)選擇, 實(shí)現(xiàn)了被用在JMS brokers中特定的有線協(xié)議,比如OpenWire. 它僅僅是實(shí)現(xiàn)通用消息操作中的一部分,并非想要覆蓋全面的消息API.
STOMP目前已經(jīng)是個(gè)成熟的協(xié)議,在wire-level方面, 它提供了一些簡(jiǎn)單的用例,但仍保持其核心設(shè)計(jì)原則:簡(jiǎn)單性和互操作性。 ### 協(xié)議概述
STOMP是基于frame的協(xié)議, 與HTTP的frame相似.一個(gè)frame包含一個(gè)command,一系列可選的headers和body.STOMP雖然是基于消息但同于也允許傳遞二進(jìn)制消息。STMOP的默認(rèn)消息格式是UTF-8,但是在消息體中同樣支持其他格式編碼。
STOMP服務(wù)器就好像是一系列的目的地, 消息會(huì)被發(fā)送到這里。STOMP協(xié)議把目的地當(dāng)作不透明的字符串,其語(yǔ)法是服務(wù)端具體的實(shí)現(xiàn)。 此外STOMP沒(méi)有定義目的地的交付語(yǔ)義是什么。 交付,或“消息交換”,語(yǔ)義的目的地可以從服務(wù)器到服務(wù)器,甚至從目的地到目的地。這使得服務(wù)器有可創(chuàng)造性的語(yǔ)義,去支持STOMP。
STOMP client的用戶代理可以充當(dāng)兩個(gè)角色(可能同時(shí)): * 作為生產(chǎn)者,通過(guò)SENDframe發(fā)送消息到server * 作為消費(fèi)者,發(fā)送SUBSCRIBEframe到目的地并且通過(guò)MESSAGEframe從server獲取消息。
STOMP版本之間的變化
STOMP 1.2 大部分向后兼容1.1. 有兩點(diǎn)不兼容的改變: * 用回車(chē)加換行符代替只用換行符結(jié)束frame * 簡(jiǎn)化了消息應(yīng)答,用專用的header
除此之外,STOMP 1.2并沒(méi)有增加新特性,而是闡述規(guī)格中的一些模糊概念,比如: * 重復(fù)的frame header條目 *?content-length和content-typeheaders的用法 * 必須支持servers STOMP frame * 連接延遲 * 作用域,訂閱的唯一,事務(wù)的標(biāo)示符 *RECEIPTframe的含義
?設(shè)計(jì)哲學(xué)
簡(jiǎn)易性,互通性是STOMP主要設(shè)計(jì)哲學(xué).
STOMP被設(shè)計(jì)成為輕量級(jí)的協(xié)議,它很容易用其他語(yǔ)言在client和server實(shí)現(xiàn)。這就意味著servers的架構(gòu)沒(méi)有太多的約束,以及沒(méi)有太多的特性比如目的地命名空間,可靠的語(yǔ)法需要去實(shí)現(xiàn)。
在這份規(guī)格書(shū)里面,注意,我們沒(méi)有明確定義的STOMP 1.2 servers特性。你應(yīng)該查閱STMOMP servers 文檔去獲得這些特性的詳細(xì)描述。
一致性
RFC 2119中詳細(xì)地解釋了MUST,?MUST NOT,?REQUIRED,?SHALL,?SHALL NOT,?SHOULD,?SHOULD NOT,RECOMMENDED,?MAY, 和?OPTIONAL這些關(guān)鍵字
為了阻止來(lái)自服務(wù)端地攻擊,保護(hù)內(nèi)存溢出,消除平臺(tái)限制,限制了不受約束的輸入。
規(guī)格中一致性的級(jí)別適用于STOMP clients and STOMP servers.
STOMP Frames
STOMP是基于幀的協(xié)議,它假定底層為一個(gè)2-way的可靠流的網(wǎng)絡(luò)協(xié)議(如TCP)。客戶端和服務(wù)器通信使用STOMP幀流通訊。幀的結(jié)構(gòu)看起來(lái)像:
COMMAND header1:value1 header2:value2Body^@幀以command字符串開(kāi)始,以EOL結(jié)束,其中包括可選回車(chē)符(13字節(jié)),緊接著是換行符(10字節(jié))。command下面是0個(gè)或多個(gè)<key>:<value>格式的header條目, 每個(gè)條目由EOL結(jié)束。一個(gè)空白行(即額外EOL)表示header結(jié)束和body開(kāi)始。body連接著NULL字節(jié)。本文檔中的例子將使用^@,在ASCII中用control-@表示,代表NULL字節(jié)。NULL字節(jié)可以選擇跟多個(gè)EOLs。欲了解更多關(guān)于STOMP幀的詳細(xì)信息,請(qǐng)參閱Augmented BNF節(jié)本文件。
本文檔中引用的所有command 和header 名字都是大小寫(xiě)敏感的.
編碼方式
commands和headers 都是用UTF-8編碼的.在用UTF-8編碼的headers中除了CONNECT和CONNECTED幀以外,任何的回車(chē)符,換行符,colon found(?)都將被轉(zhuǎn)義.
轉(zhuǎn)義的目的在于允許header中的鍵值包含那些把octets當(dāng)作值的frame header.
為了向后兼容STOMP 1.0,?CONNECT和CONNECTED不會(huì)轉(zhuǎn)義回車(chē)符,換行符,colon found(?)
C風(fēng)格的字符串轉(zhuǎn)義被用在UTF-8編碼的headers中去轉(zhuǎn)義回車(chē)符,換行符以及colon found.當(dāng)解碼headers時(shí),必須使用下列轉(zhuǎn)換: * \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)
未定義轉(zhuǎn)義序列如\t(octet 92 and 116)必須被視為一個(gè)致命的錯(cuò)誤。相反,當(dāng)編碼幀頭,必須使用逆轉(zhuǎn)變.
The STOMP 1.0 specification included many example frames with padding in the headers and many servers and clients were implemented to trim or pad header values. This causes problems if applications want to send headers that SHOULD not get trimmed. In STOMP 1.2, clients and servers MUST never trim or pad headers with spaces.
Body
只有SEND,?MESSAGE, 和ERROR幀有body。所有其他的幀不能有body。
標(biāo)準(zhǔn)header
大多數(shù)被用的header都有特殊的含義。
Header content-length
所有的幀可能都包括有content-length的header。它定義了消息體的大小。如果header包含了content-length, 包含空字節(jié)的消息體的最大字節(jié)數(shù)不能超過(guò)這個(gè)數(shù). 幀仍然需要以空字節(jié)結(jié)束。
如幀體存在,SEND,?MESSAGE?和?ERROR幀應(yīng)該包含content-length.如果幀體包含空字節(jié),那么這個(gè)幀必須包括content-length.
Header content-type
如果幀體存在,SEND,?MESSAGE?和?ERROR幀應(yīng)該包含content-type幫助接受者去理解幀體.如果設(shè)置了content-type, 它的值必須是描述幀體格式的MINE類(lèi)型.否則,接收者應(yīng)該認(rèn)為幀體格式為二進(jìn)制Blob.
以text/開(kāi)頭的MINE類(lèi)型的默認(rèn)文本編碼是UTF-8. 如果你正在用一個(gè)基于MINE類(lèi)型的不同編碼, 你應(yīng)該添加;charset=<encoding>MINE類(lèi)型。例如:如果你發(fā)送一個(gè)UTF-16編碼的HTML body, 應(yīng)該設(shè)置text/html;charset=utf-16.?;charset=<encoding>也能添加到任何非text/?MINE類(lèi)型后去作為說(shuō)明。UTF-8編碼的XML是個(gè)很好的例子。它的編碼被設(shè)置為application/xml;charset=utf-8.
所有STOMP客戶端和服務(wù)端必須支持UTF-8編碼和解碼。因此,為了最大限度地使用在異構(gòu)環(huán)境中的互操作性,建議基于文本的內(nèi)容使用UTF-8編碼.
Header receipt
任何除了CONNECT的客戶端幀可以為receipt?header指定任何值。這會(huì)讓服務(wù)端應(yīng)答帶有RECEIPT的客戶端幀的處理過(guò)程。
Repeated Header Entries
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. A STOMP server MAY ‘update’ header values by either prepending headers to the message or modifying a header in-place in the message.
如果client或者server受到重復(fù)的header條目,只有第一個(gè)會(huì)被用作header條目的值。其他的值僅僅用來(lái)維持狀態(tài)改變,或者被丟棄。
例如,如果client收到:
MESSAGE foo:World foo:Hello^@foo?header的值為World.
大小限制
為了客戶端濫用服務(wù)端的內(nèi)存分配,服務(wù)端可以設(shè)置可分配的內(nèi)存大小:
- 單個(gè)幀允許幀頭的個(gè)數(shù)
- header中每一行的最大長(zhǎng)度
- 幀體的大小
如果超出了這些限制,server應(yīng)該向client發(fā)送一個(gè)error?frame,然后關(guān)閉連接.
連接延遲
STOMP servers必須支持client快速地連接server和斷開(kāi)連接。 這意味著server在連接重置前只允許被關(guān)閉的連接短時(shí)間地延遲.
結(jié)果就是,在socket重置前client可能不會(huì)收到server發(fā)來(lái)的最后一個(gè)frame(比如ERROR或者RECEIPTframe去應(yīng)答DISCONNECTframe)
Connecting
STOMP client通過(guò)CONNECTframe與server建立流或者TCP連接.
CONNECT accept-version:1.2 host:stomp.github.org^@如果server收到請(qǐng)求,將返回CONNECTEDframe:
CONNECTED version:1.2^@server能拒絕所有的連接請(qǐng)求。server應(yīng)該響應(yīng)ERRORframe去說(shuō)明為什么連接被拒絕然后關(guān)閉連接。
CONNECT or STOMP Frame
STOMP servers 處理STOMPframe必須和處理CONNECTframe一樣。STOMP1.2?clients應(yīng)該繼續(xù)使用CONNECTcommand去向后兼容1.0.
使用STOMPframe的clients只能連接上STOMP1.2?servers(以及一些STOMP1.1 servers),但是好處在于協(xié)議探針能夠從HTTP連接中區(qū)分開(kāi)STOMP連接。
STOMP 1.2 clients?必須設(shè)置以下headers: *?accept-version: clients支持的STOMP的版本號(hào)。詳情見(jiàn)Protocol_Negotiation?*?host:client希望連接的虛擬主機(jī)名字,建議設(shè)置已經(jīng)連接的socket為主機(jī)名,或者任何名字。如果headers沒(méi)有匹配到任何可用的虛擬主機(jī),支持虛擬主機(jī)的servers將選擇默認(rèn)的虛擬主機(jī)或者拒絕連接。
STOMP 1.2 clients可選擇設(shè)置以下headers: *?login: 用于在server驗(yàn)證的用戶id *passcode: 用于在server驗(yàn)證的密碼 *?heart-beat:?心跳設(shè)置
CONNECTED Frame
STOMP 1.2 servers?必須設(shè)置以下headers:
- version: 會(huì)話中STOMP版本。詳情見(jiàn)Protocol_Negotiation
STOMP 1.2 servers可選擇設(shè)置以下headers:
- heart-beat:?心跳設(shè)置
- session: 唯一的會(huì)話identifier
-
server: 描述STOMP server信息。它必須包含server-name,可以包含一些注釋信息(用空格分開(kāi))?server-name后面也可以帶著可選的版本號(hào).
server = name ["/" version] *(comment)例如:
server:Apache/1.3.9
Protocol Negotiation
STOMP1.1 以后的版本,CONNECTframe必須包括accept-versionheader.它的值為clients支持的STOMP版本號(hào),多個(gè)版本號(hào)用,隔開(kāi)。如果不存在accept-versionheader,那么表明clients只支持1.0.
在一次會(huì)話中將使用雙方都支持的最高版本。
例如,如果client發(fā)送:
CONNECT accept-version:1.0,1.1,2.0 host:stomp.github.org^@server將返回與客戶端同時(shí)支持的最高版本。
CONNECTED version:1.1^@如果client和server不支持共同的協(xié)議版本,server必須返回如下的ERRORframe,然后斷開(kāi)連接。
ERROR version:1.2,2.1 content-type:text/plainSupported protocol versions are 1.2 2.1^@心跳
心跳被用于去測(cè)試底層TCP連接的可用性,確保遠(yuǎn)端服務(wù)處于活動(dòng)狀態(tài)。
要使用心跳,每個(gè)部分必須聲明它能干什么以及想要其他部分干什么. 通過(guò)在CONNECT和CONNECTEDframe中增加heart-beatheader, 讓心跳在會(huì)話開(kāi)始被定義好。heart-beatheader必須包含兩個(gè)用逗號(hào)隔開(kāi)的正整數(shù)。
第一個(gè)數(shù)字代表發(fā)送方能做什么: *?0表示它不能發(fā)送心跳 * 否則它是能保證兩次心跳的最小毫秒數(shù)
第二個(gè)數(shù)字代表發(fā)送方能獲得什么: *?0表示它不想接收心跳 * 否則它表示兩次心跳期望的毫秒數(shù)
heart-beatheader是OPTIONAL的。沒(méi)有的話會(huì)被當(dāng)作heart-beat:0,0header 處理,意思就是說(shuō)它不會(huì)發(fā)送心跳并且不想接收心跳。
heart-beatheader提供了足夠的信息去了解每個(gè)部分心跳是否可用,發(fā)送到哪里,頻率的大小.
原始frame像這個(gè)樣子:
CONNECT heart-beat:<cx>,<cy>CONNECTED: heart-beat:<sx>,<sy>對(duì)于client發(fā)送server的心跳: * 如果<cx>為0(client不能發(fā)送心跳)或者<sy>為0(server不想接收心跳),將不起任何作用。 * 否則心跳頻率為MAX(<cx>,<sy>)毫秒數(shù).
相反,<sx>和<cy>同樣是這樣的.
關(guān)于心跳本身,通過(guò)網(wǎng)絡(luò)連接收到的任何數(shù)據(jù)表明遠(yuǎn)端服務(wù)是可用的。在給定的指向,如果心跳的頻率被期望是<n>毫秒:
- 發(fā)送者必須每<n>毫秒發(fā)送新數(shù)據(jù)。
- 如果發(fā)送者沒(méi)有真實(shí)的STOMP frame,必須發(fā)送一個(gè)end-of-line (EOL)
- 如果接受者在規(guī)定的時(shí)間內(nèi)沒(méi)有收到新數(shù)據(jù),表明連接已經(jīng)斷開(kāi)
- 由于時(shí)間誤差,接收者應(yīng)該容錯(cuò)和考慮定義錯(cuò)誤的界限
Client Frames
client可以發(fā)送下列列表以外的frame,但是STOMP1.2 server會(huì)響應(yīng)ERRORframe,然后關(guān)閉連接。
- SEND
- SUBSCRIBE
- UNSUBSCRIBE
- BEGIN
- COMMIT
- ABORT
- ACK
- NACK
- DISCONNECT
SEND
SENDframe發(fā)送消息到目的地,它必須包含表示目的地地址的destinationheader.SENDframe body是被發(fā)送的消息。例如:
SEND destination:/queue/a content-type:text/plainhello queue a ^@這個(gè)消息被發(fā)送到/queue/a.注意STOMP把目的地看作為一個(gè)不透明的字符串,沒(méi)有目的地假設(shè)的交互語(yǔ)義.你應(yīng)該查閱STOMP server文檔,搞清楚如何構(gòu)造目的地名字。
可靠的消息語(yǔ)義是server指定的,依賴備用的目的地的值和其他消息headers,比如事務(wù)headers,或者其他server指定的消息headers。
SEND可以添加transactionheader來(lái)支持事務(wù)處理.
如果body存在,那么SENDframe應(yīng)該包含一個(gè)content-length和content-typeheader
一個(gè)應(yīng)用可以給SENDframe增加任意多個(gè)用戶定義的headers。 通常用于用戶定義的頭,讓消費(fèi)者能夠根據(jù)應(yīng)用程序定義的報(bào)頭使用選擇訂閱幀過(guò)濾消息。 被定義的用戶必須通過(guò)MESSAGEframe傳送。
如果server不能無(wú)故成功處理SENDframe,那么server必須向client發(fā)送ERRORframe然后關(guān)閉連接。
SUBSCRIBE
SUBSCRIBEframe用于注冊(cè)給定的目的地.和SENDframe一樣,SUBSCRIBEframe需要包含destinationheader表明client想要訂閱目的地。 被訂閱的目的地收到的任何消息將通過(guò)MESSAGEframe發(fā)送給client。?ackheader控制著確認(rèn)模式。
例子:
SUBSCRIBE id:0 destination:/queue/foo ack:client^@如果server不能成功創(chuàng)建此次訂閱,那么server將返回ERRORframe然后關(guān)閉連接。
STOMP服務(wù)器可能支持額外的服務(wù)器特定的頭文件,來(lái)自定義有關(guān)訂閱傳遞語(yǔ)義.
SUBSCRIBE id Header
一個(gè)單連接可以對(duì)應(yīng)多個(gè)開(kāi)放的servers訂閱,所以必須包含idheader去唯一標(biāo)示這個(gè)訂閱.這個(gè)idframe可以把此次訂閱與接下來(lái)的MESSAGEframe和UNSUBSCRIBEframe聯(lián)系起來(lái)。
在相同的連接中,不同的訂閱必須擁有不同訂閱id。
SUBSCRIBE ack Header
ackheader可用的值有auto,?client,client-individual, 默認(rèn)為auto.
當(dāng)ack為auto時(shí),client收到server發(fā)來(lái)的消息后不需要回復(fù)ACKframe.server假定消息發(fā)出去后client就已經(jīng)收到。這種確認(rèn)方式可以減少消息傳輸?shù)拇螖?shù).
當(dāng)ack為client時(shí), client必須發(fā)送ACkframe給servers, 讓它處理消息.如果在client發(fā)送ACKframe之前連接斷開(kāi)了,那么server將假設(shè)消息沒(méi)有被處理,可能會(huì)再次發(fā)送消息給另外的客戶端。client發(fā)送的ACKframe被當(dāng)作時(shí)積累的確認(rèn)。這就意味這種確認(rèn)方式會(huì)去操作ACKframe指定的消息和訂閱的所有消息
由于client不能處理某些消息,所以client應(yīng)該發(fā)送NACKframe去告訴server它不能消費(fèi)這些消息。
當(dāng)ack模式是client-individual,確認(rèn)工作就像客戶端確認(rèn)模式(除了由客戶端發(fā)送的ACK或NACK幀)不會(huì)被累計(jì)。這意味著,后續(xù)ACK,?NACK消息幀,也不能影響前面的消息的確認(rèn)。
UNSUBSCRIBE
UNSUBSCRIBEframe被用于去移除已經(jīng)存在訂閱。一旦訂閱被刪除后,STOMP連接將不再會(huì)收到來(lái)自訂閱發(fā)出的消息。
一個(gè)單連接可以對(duì)應(yīng)多個(gè)開(kāi)放的server訂閱,所以必須包含idheader去唯一標(biāo)示被刪除的訂閱.這個(gè)header中的id必須匹配已存在訂閱.
例如:
UNSUBSCRIBE id:0^@ACK
ACK用client和client-individual去確認(rèn)訂閱消息的消費(fèi).只有通過(guò)ACK確認(rèn)過(guò)后,訂閱的消息才算是被消費(fèi).
ACKframe必須包含一個(gè)idheader去匹配將要被確認(rèn)的ackheader中的id.可以選擇地指定transactionheader表明消息確認(rèn)應(yīng)該是命名事務(wù)地一部分。
ACK id:12345 transaction:tx1^@NACK
NACK有ACK相反地作用。它地作用是告訴server client不想消費(fèi)這個(gè)消息。server然后發(fā)送這個(gè)消息給另外的client,丟棄它或者把它放在無(wú)效的消息隊(duì)列中。這種準(zhǔn)確的行為是server特定的。
NACK有相同的ACKheaders:?id(必選)和transaction(可選)。
NACK適用于單個(gè)消息(訂閱的ack模式為client-individual), 或者那些還沒(méi)有被ACK'ed和NACK'ed的消息(訂閱模式ack為client).
BEGIN
BEGIN用于事務(wù)的開(kāi)始。事務(wù)被用于發(fā)送和確認(rèn)消息,被發(fā)送和被確認(rèn)的消息在事務(wù)過(guò)程中會(huì)被自動(dòng)處理。
BEGIN transaction:tx1^@transactionheader是必填的,并且事務(wù)id將被用于在SEND, COMMIT, ABORT, ACK, and NACK frames去綁定命名的事務(wù).在相同的連接中,不同事務(wù)必須用不同的id
如果client發(fā)送DISCONNECTframe或者TCP連接失敗,任何已開(kāi)始但沒(méi)有提交的事務(wù)默認(rèn)都會(huì)被中斷.
COMMIT
COMMIT用于在過(guò)程中提交事務(wù).
COMMIT transaction:tx1^@transactionheader是必填的并且必須指定將要提交的事務(wù)的id.
ABORT
ABORT用于在過(guò)程中回滾事務(wù).
ABORT transaction:tx1^@transactionheader是必填的并且必須指定將要提交的事務(wù)的id.
DISCONNECT
client能在任何時(shí)候斷開(kāi)server的連接,但是不能保證已經(jīng)發(fā)送的frame已經(jīng)到達(dá)了server。為了讓這一切顯得不那么暴力,client確保所有已經(jīng)發(fā)送的frames已經(jīng)被server收到,client應(yīng)該做以下3點(diǎn):
發(fā)送帶有receiptheader的DISCONNECTframe
DISCONNECTreceipt:77^@等待帶有RECEIPTframe的響應(yīng)
RECEIPTreceipt-id:77^@關(guān)閉socket
注意,如果server過(guò)早地關(guān)閉socket,client將不會(huì)收到期望地RECEIPTframe.見(jiàn)Connection_Lingering
client發(fā)送DISCONNECTframe后不必要在發(fā)送任何frame.
Server Frames
server偶爾也會(huì)發(fā)送frame給客戶端(除了連接最初的CONNECTEDframe).
這些frames為: *?MESSAGE?*?RECEIPT?*?ERROR
MESSAGE
MESSAGEframe用于將訂閱的消息發(fā)送給client.
MESSAGEframe必須包含destinationheader表明信息要到達(dá)的目的地。如果消息已經(jīng)用STOMP發(fā)送,那么destinationheader應(yīng)該和SENDframe中的一樣。
MESSAGEframe必須包含帶有唯一標(biāo)識(shí)的message-idheader和帶有將接收消息的訂閱的idsubscriptionheader.
如果從訂閱收到的消息需要明確作出確認(rèn)(client或者client-individual模式),那么MESSAGEframe必須包含帶有任何值的ackheader.這個(gè)header將把消息和后來(lái)的ACK,NACKframe關(guān)聯(lián)起來(lái)。
下面這個(gè)frame body包含了消息的內(nèi)容:
MESSAGE subscription:0 message-id:007 destination:/queue/a content-type:text/plainhello queue a^@如果frame body包含內(nèi)容的話,MESSAGEframe應(yīng)該包含content-lengthheader和content-typeheader.
除了那些server指定的headers, 消息被發(fā)送到目的地時(shí),MESSAGEframe同樣應(yīng)該包括所有用戶定義的headers.查閱有關(guān)文檔,找出那些server指定添加到messages的headers.
RECEIPT
server成功處理請(qǐng)求帶有receipt的client frame后, 將發(fā)送RECEIPTframe到client.RECEIPTframe必須包含receipt-id?header,它的值為client frame中receiptheader的值。
RECEIPT receipt-id:message-12345^@RECEIPTframe是作為server處理的client frame后的應(yīng)答. 既然STOMP是基于流的,那么receipt也是對(duì)server已經(jīng)收到所有的frames的累積確認(rèn)。但是,以前的frames可能并沒(méi)有被完全處理。如果clients斷開(kāi)連接,以前接收到的frames應(yīng)該繼續(xù)被server處理。
ERROR
如果出錯(cuò)的話,server將發(fā)送ERRORframe.這種情況下,server還應(yīng)該斷開(kāi)連接。查看下一章connection lingering?ERRORframe應(yīng)該包含帶有簡(jiǎn)單錯(cuò)誤信息的messageheader,或者Body包含詳細(xì)的描述信息,也可能沒(méi)有。
ERROR receipt-id:message-12345 content-type:text/plain content-length:171 message: malformed frame receivedThe message: ----- MESSAGE destined:/queue/a receipt:message-12345Hello queue a! ----- Did not contain a destination header, which is REQUIRED for message propagation. ^@如果錯(cuò)誤關(guān)聯(lián)到了具體的某個(gè)client frame,那么server應(yīng)該增加額外的headers去識(shí)別引起錯(cuò)誤的frame。例如,如果frame包含receiptheader,ERRORframe應(yīng)該設(shè)置receipt-idheader的值為引起錯(cuò)誤的frame的receiptheader的值。
如果frame body包含內(nèi)容的話,ERRORframe應(yīng)該包含content-lengthheader和content-typeheader
Frames and Headers
除了上述標(biāo)準(zhǔn)headers之外(content-length,?content-type,?receipt),下面列出了所有規(guī)范中定義的headers:
- CONNECT or STOMP
- REQUIRED: accept-version, host
- OPTIONAL: login, passcode, heart-beat
- CONNECTED
- REQUIRED: version
- OPTIONAL: session, server, heart-beat
- SEND
- REQUIRED: destination
- OPTIONAL: transaction
- SUBSCRIBE
- REQUIRED: destination, id
- OPTIONAL: ack
- UNSUBSCRIBE
- REQUIRED: id
- OPTIONAL: none
- ACK or NACK
- REQUIRED: id
- OPTIONAL: transaction
- BEGIN or COMMIT or ABORT
- REQUIRED: transaction
- OPTIONAL: none
- DISCONNECT
- REQUIRED: none
- OPTIONAL: receipt
- MESSAGE
- REQUIRED: destination, message-id, subscription
- OPTIONAL: ack
- RECEIPT
- REQUIRED: receipt-id
- OPTIONAL: none
- ERROR
- REQUIRED: none
- OPTIONAL: message
除此之外,SEND和MESSAGEframes可能包含任意的用戶定義的headers ,它們會(huì)成為carried message的一部分。同樣,ERRORframe應(yīng)該包含額外的headers來(lái)識(shí)別引起錯(cuò)誤的frame。
最終,STOMP servers可以用額外的headers去訪問(wèn)持久化或者有效期特性.查閱server文檔獲得更多信息。
Augmented BNF
A STOMP session can be more formally described using the Backus-Naur Form (BNF) grammar used in HTTP/1.1 RFC 2616.
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*frameframe = command EOL*( header EOL )EOL*OCTETNULL*( EOL )command = client-command | server-commandclient-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
This specification is licensed under the?Creative Commons Attribution v3.0?license.
轉(zhuǎn)載于:https://www.cnblogs.com/davidwang456/p/4449428.html
總結(jié)
以上是生活随笔為你收集整理的STOMP协议规范--转载的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問(wèn)題。
- 上一篇: Logback日志使用详解
- 下一篇: spring源码分析之spring-me