STOMP 協(xié)議

摘要

STOMP是一個簡單的可互操作的協(xié)議, 被用于通過中間服務器在客戶端之間進行異步消息傳遞氢惋。它定義了一種在客戶端與服務端進行消息傳遞的文本格式.

STOMP已經(jīng)被使用了很多年洞翩,并且支持很多消息brokers和客戶端庫稽犁。這個規(guī)范定義STOMP1.2協(xié)議以及對1.1版本的更新。

發(fā)送反饋到stomp-spec@googlegroups.com.

概述

背景

由于需要用腳本語言如Ruby,Python,Perl去連接企業(yè)級的消息brokers, STOMP產(chǎn)生了.在這種情況下骚亿,STMOP實現(xiàn)了一些簡單的操作已亥,比如可靠地發(fā)送單一的消息,然后斷開或者從目的地消費所有消息来屠。

STOMP是除AMQP開放消息協(xié)議之外地另外一個選擇, 實現(xiàn)了被用在JMS brokers中特定的有線協(xié)議虑椎,比如OpenWire. 它僅僅是實現(xiàn)通用消息操作中的一部分,并非想要覆蓋全面的消息API.

STOMP目前已經(jīng)是個成熟的協(xié)議俱笛,在wire-level方面, 它提供了一些簡單的用例捆姜,但仍保持其核心設計原則:簡單性和互操作性。 ### 協(xié)議概述

STOMP是基于frame的協(xié)議, 與HTTP的frame相似.一個frame包含一個command嫂粟,一系列可選的headers和body.STOMP雖然是基于消息但同于也允許傳遞二進制消息娇未。STMOP的默認消息格式是UTF-8,但是在消息體中同樣支持其他格式編碼。

STOMP服務器就好像是一系列的目的地, 消息會被發(fā)送到這里星虹。STOMP協(xié)議把目的地當作不透明的字符串零抬,其語法是服務端具體的實現(xiàn)。 此外STOMP沒有定義目的地的交付語義是什么宽涌。 交付平夜,或“消息交換”,語義的目的地可以從服務器到服務器卸亮,甚至從目的地到目的地忽妒。這使得服務器有可創(chuàng)造性的語義,去支持STOMP兼贸。

STOMP client的用戶代理可以充當兩個角色(可能同時): * 作為生產(chǎn)者段直,通過SENDframe發(fā)送消息到server * 作為消費者,發(fā)送SUBSCRIBEframe到目的地并且通過MESSAGEframe從server獲取消息溶诞。

STOMP版本之間的變化

STOMP 1.2 大部分向后兼容1.1. 有兩點不兼容的改變: * 用回車加換行符代替只用換行符結(jié)束frame * 簡化了消息應答鸯檬,用專用的header

除此之外,STOMP 1.2并沒有增加新特性螺垢,而是闡述規(guī)格中的一些模糊概念喧务,比如: * 重復的frame header條目 *content-length和content-typeheaders的用法 * 必須支持servers STOMP frame * 連接延遲 * 作用域,訂閱的唯一枉圃,事務的標示符 *RECEIPTframe的含義

設計哲學

簡易性功茴,互通性是STOMP主要設計哲學.

STOMP被設計成為輕量級的協(xié)議,它很容易用其他語言在client和server實現(xiàn)孽亲。這就意味著servers的架構(gòu)沒有太多的約束坎穿,以及沒有太多的特性比如目的地命名空間,可靠的語法需要去實現(xiàn)返劲。

在這份規(guī)格書里面玲昧,注意犯祠,我們沒有明確定義的STOMP 1.2 servers特性。你應該查閱STMOMP servers 文檔去獲得這些特性的詳細描述酌呆。

一致性

RFC 2119中詳細地解釋了MUST,MUST NOT,REQUIRED,SHALL,SHALL NOT,SHOULD,SHOULD NOT,RECOMMENDED,MAY, 和OPTIONAL這些關(guān)鍵字

為了阻止來自服務端地攻擊,保護內(nèi)存溢出搔耕,消除平臺限制隙袁,限制了不受約束的輸入。

規(guī)格中一致性的級別適用于STOMP clients and STOMP servers.

STOMP Frames

STOMP是基于幀的協(xié)議弃榨,它假定底層為一個2-way的可靠流的網(wǎng)絡協(xié)議(如TCP)菩收。客戶端和服務器通信使用STOMP幀流通訊鲸睛。幀的結(jié)構(gòu)看起來像:

COMMAND

header1:value1

header2:value2

Body^@

幀以command字符串開始,以EOL結(jié)束娜饵,其中包括可選回車符(13字節(jié)),緊接著是換行符(10字節(jié))官辈。command下面是0個或多個:格式的header條目, 每個條目由EOL結(jié)束箱舞。一個空白行(即額外EOL)表示header結(jié)束和body開始。body連接著NULL字節(jié)拳亿。本文檔中的例子將使用^@,在ASCII中用control-@表示晴股,代表NULL字節(jié)。NULL字節(jié)可以選擇跟多個EOLs肺魁。欲了解更多關(guān)于STOMP幀的詳細信息电湘,請參閱Augmented BNF節(jié)本文件。

本文檔中引用的所有command 和header 名字都是大小寫敏感的.

編碼方式

commands和headers 都是用UTF-8編碼的.在用UTF-8編碼的headers中除了CONNECT和CONNECTED幀以外鹅经,任何的回車符寂呛,換行符,colon found(?)都將被轉(zhuǎn)義.

轉(zhuǎn)義的目的在于允許header中的鍵值包含那些把octets當作值的frame header.

為了向后兼容STOMP 1.0,CONNECT和CONNECTED不會轉(zhuǎn)義回車符瘾晃,換行符贷痪,colon found(?)

C風格的字符串轉(zhuǎn)義被用在UTF-8編碼的headers中去轉(zhuǎn)義回車符,換行符以及colon found.當解碼headers時酗捌,必須使用下列轉(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)必須被視為一個致命的錯誤呢诬。相反,當編碼幀頭胖缤,必須使用逆轉(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。

標準header

大多數(shù)被用的header都有特殊的含義哪廓。

Header content-length

所有的幀可能都包括有content-length的header狗唉。它定義了消息體的大小。如果header包含了content-length, 包含空字節(jié)的消息體的最大字節(jié)數(shù)不能超過這個數(shù). 幀仍然需要以空字節(jié)結(jié)束涡真。

如幀體存在分俯,SEND,MESSAGE和ERROR幀應該包含content-length.如果幀體包含空字節(jié)肾筐,那么這個幀必須包括content-length.

Header content-type

如果幀體存在,SEND,MESSAGE和ERROR幀應該包含content-type幫助接受者去理解幀體.如果設置了content-type, 它的值必須是描述幀體格式的MINE類型.否則缸剪,接收者應該認為幀體格式為二進制Blob.

以text/開頭的MINE類型的默認文本編碼是UTF-8. 如果你正在用一個基于MINE類型的不同編碼, 你應該添加;charset=MINE類型吗铐。例如:如果你發(fā)送一個UTF-16編碼的HTML body, 應該設置text/html;charset=utf-16.;charset=也能添加到任何非text/MINE類型后去作為說明杏节。UTF-8編碼的XML是個很好的例子唬渗。它的編碼被設置為application/xml;charset=utf-8.

所有STOMP客戶端和服務端必須支持UTF-8編碼和解碼。因此奋渔,為了最大限度地使用在異構(gòu)環(huán)境中的互操作性镊逝,建議基于文本的內(nèi)容使用UTF-8編碼.

Header receipt

任何除了CONNECT的客戶端幀可以為receiptheader指定任何值。這會讓服務端應答帶有RECEIPT的客戶端幀的處理過程嫉鲸。

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受到重復的header條目撑蒜,只有第一個會被用作header條目的值。其他的值僅僅用來維持狀態(tài)改變玄渗,或者被丟棄座菠。

例如,如果client收到:

MESSAGE

foo:World

foo:Hello

^@

fooheader的值為World.

大小限制

為了客戶端濫用服務端的內(nèi)存分配捻爷,服務端可以設置可分配的內(nèi)存大小:

單個幀允許幀頭的個數(shù)

header中每一行的最大長度

幀體的大小

如果超出了這些限制辈灼,server應該向client發(fā)送一個errorframe,然后關(guān)閉連接.

連接延遲

STOMP servers必須支持client快速地連接server和斷開連接。 這意味著server在連接重置前只允許被關(guān)閉的連接短時間地延遲.

結(jié)果就是也榄,在socket重置前client可能不會收到server發(fā)來的最后一個frame(比如ERROR或者RECEIPTframe去應答DISCONNECTframe)

Connecting

STOMP client通過CONNECTframe與server建立流或者TCP連接.

CONNECT

accept-version:1.2

host:stomp.github.org

^@

如果server收到請求巡莹,將返回CONNECTEDframe:

CONNECTED

version:1.2

^@

server能拒絕所有的連接請求。server應該響應ERRORframe去說明為什么連接被拒絕然后關(guān)閉連接甜紫。

CONNECT or STOMP Frame

STOMP servers 處理STOMPframe必須和處理CONNECTframe一樣降宅。STOMP1.2clients應該繼續(xù)使用CONNECTcommand去向后兼容1.0.

使用STOMPframe的clients只能連接上STOMP1.2servers(以及一些STOMP1.1 servers),但是好處在于協(xié)議探針能夠從HTTP連接中區(qū)分開STOMP連接。

STOMP 1.2 clients必須設置以下headers: *accept-version: clients支持的STOMP的版本號囚霸。詳情見Protocol_Negotiation*host:client希望連接的虛擬主機名字腰根,建議設置已經(jīng)連接的socket為主機名,或者任何名字拓型。如果headers沒有匹配到任何可用的虛擬主機额嘿,支持虛擬主機的servers將選擇默認的虛擬主機或者拒絕連接。

STOMP 1.2 clients可選擇設置以下headers: *login: 用于在server驗證的用戶id *passcode: 用于在server驗證的密碼 *heart-beat:心跳設置

CONNECTED Frame

STOMP 1.2 servers必須設置以下headers:

version: 會話中STOMP版本劣挫。詳情見Protocol_Negotiation

STOMP 1.2 servers可選擇設置以下headers:

heart-beat:心跳設置

session: 唯一的會話identifier

server: 描述STOMP server信息册养。它必須包含server-name,可以包含一些注釋信息(用空格分開)server-name后面也可以帶著可選的版本號.

server = name ["/" version] *(comment)

例如:

server:Apache/1.3.9

Protocol Negotiation

STOMP1.1 以后的版本,CONNECTframe必須包括accept-versionheader.它的值為clients支持的STOMP版本號压固,多個版本號用,隔開球拦。如果不存在accept-versionheader,那么表明clients只支持1.0.

在一次會話中將使用雙方都支持的最高版本。

例如,如果client發(fā)送:

CONNECT

accept-version:1.0,1.1,2.0

host:stomp.github.org

^@

server將返回與客戶端同時支持的最高版本坎炼。

CONNECTED

version:1.1

^@

如果client和server不支持共同的協(xié)議版本,server必須返回如下的ERRORframe,然后斷開連接愧膀。

ERROR

version:1.2,2.1

content-type:text/plain

Supported protocol versions are 1.2 2.1^@

心跳

心跳被用于去測試底層TCP連接的可用性,確保遠端服務處于活動狀態(tài)谣光。

要使用心跳檩淋,每個部分必須聲明它能干什么以及想要其他部分干什么. 通過在CONNECT和CONNECTEDframe中增加heart-beatheader, 讓心跳在會話開始被定義好。heart-beatheader必須包含兩個用逗號隔開的正整數(shù)萄金。

第一個數(shù)字代表發(fā)送方能做什么: *0表示它不能發(fā)送心跳 * 否則它是能保證兩次心跳的最小毫秒數(shù)

第二個數(shù)字代表發(fā)送方能獲得什么: *0表示它不想接收心跳 * 否則它表示兩次心跳期望的毫秒數(shù)

heart-beatheader是OPTIONAL的狼钮。沒有的話會被當作heart-beat:0,0header 處理,意思就是說它不會發(fā)送心跳并且不想接收心跳捡絮。

heart-beatheader提供了足夠的信息去了解每個部分心跳是否可用,發(fā)送到哪里莲镣,頻率的大小.

原始frame像這個樣子:

CONNECT

heart-beat:,

CONNECTED:

heart-beat:,

對于client發(fā)送server的心跳: * 如果為0(client不能發(fā)送心跳)或者為0(server不想接收心跳),將不起任何作用福稳。 * 否則心跳頻率為MAX(,)毫秒數(shù).

相反,和同樣是這樣的.

關(guān)于心跳本身瑞侮,通過網(wǎng)絡連接收到的任何數(shù)據(jù)表明遠端服務是可用的的圆。在給定的指向,如果心跳的頻率被期望是毫秒:

發(fā)送者必須每毫秒發(fā)送新數(shù)據(jù)半火。

如果發(fā)送者沒有真實的STOMP frame越妈,必須發(fā)送一個end-of-line (EOL)

如果接受者在規(guī)定的時間內(nèi)沒有收到新數(shù)據(jù),表明連接已經(jīng)斷開

由于時間誤差钮糖,接收者應該容錯和考慮定義錯誤的界限

Client Frames

client可以發(fā)送下列列表以外的frame梅掠,但是STOMP1.2 server會響應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/plain

hello queue a

^@

這個消息被發(fā)送到/queue/a.注意STOMP把目的地看作為一個不透明的字符串,沒有目的地假設的交互語義.你應該查閱STOMP server文檔消痛,搞清楚如何構(gòu)造目的地名字且叁。

可靠的消息語義是server指定的,依賴備用的目的地的值和其他消息headers秩伞,比如事務headers逞带,或者其他server指定的消息headers。

SEND可以添加transactionheader來支持事務處理.

如果body存在纱新,那么SENDframe應該包含一個content-length和content-typeheader

一個應用可以給SENDframe增加任意多個用戶定義的headers展氓。 通常用于用戶定義的頭,讓消費者能夠根據(jù)應用程序定義的報頭使用選擇訂閱幀過濾消息怒炸。 被定義的用戶必須通過MESSAGEframe傳送带饱。

如果server不能無故成功處理SENDframe,那么server必須向client發(fā)送ERRORframe然后關(guān)閉連接。

SUBSCRIBE

SUBSCRIBEframe用于注冊給定的目的地.和SENDframe一樣,SUBSCRIBEframe需要包含destinationheader表明client想要訂閱目的地勺疼。 被訂閱的目的地收到的任何消息將通過MESSAGEframe發(fā)送給client教寂。ackheader控制著確認模式。

例子:

SUBSCRIBE

id:0

destination:/queue/foo

ack:client

^@

如果server不能成功創(chuàng)建此次訂閱执庐,那么server將返回ERRORframe然后關(guān)閉連接酪耕。

STOMP服務器可能支持額外的服務器特定的頭文件,來自定義有關(guān)訂閱傳遞語義.

SUBSCRIBE id Header

一個單連接可以對應多個開放的servers訂閱,所以必須包含idheader去唯一標示這個訂閱.這個idframe可以把此次訂閱與接下來的MESSAGEframe和UNSUBSCRIBEframe聯(lián)系起來轨淌。

在相同的連接中迂烁,不同的訂閱必須擁有不同訂閱id。

SUBSCRIBE ack Header

ackheader可用的值有auto,client,client-individual, 默認為auto.

當ack為auto時递鹉,client收到server發(fā)來的消息后不需要回復ACKframe.server假定消息發(fā)出去后client就已經(jīng)收到盟步。這種確認方式可以減少消息傳輸?shù)拇螖?shù).

當ack為client時, client必須發(fā)送ACkframe給servers, 讓它處理消息.如果在client發(fā)送ACKframe之前連接斷開了,那么server將假設消息沒有被處理躏结,可能會再次發(fā)送消息給另外的客戶端却盘。client發(fā)送的ACKframe被當作時積累的確認。這就意味這種確認方式會去操作ACKframe指定的消息和訂閱的所有消息

由于client不能處理某些消息媳拴,所以client應該發(fā)送NACKframe去告訴server它不能消費這些消息黄橘。

當ack模式是client-individual,確認工作就像客戶端確認模式(除了由客戶端發(fā)送的ACK或NACK幀)不會被累計屈溉。這意味著塞关,后續(xù)ACK,NACK消息幀,也不能影響前面的消息的確認子巾。

UNSUBSCRIBE

UNSUBSCRIBEframe被用于去移除已經(jīng)存在訂閱帆赢。一旦訂閱被刪除后,STOMP連接將不再會收到來自訂閱發(fā)出的消息线梗。

一個單連接可以對應多個開放的server訂閱,所以必須包含idheader去唯一標示被刪除的訂閱.這個header中的id必須匹配已存在訂閱.

例如:

UNSUBSCRIBE

id:0

^@

ACK

ACK用client和client-individual去確認訂閱消息的消費.只有通過ACK確認過后匿醒,訂閱的消息才算是被消費.

ACKframe必須包含一個idheader去匹配將要被確認的ackheader中的id.可以選擇地指定transactionheader表明消息確認應該是命名事務地一部分。

ACK

id:12345

transaction:tx1

^@

NACK

NACK有ACK相反地作用缠导。它地作用是告訴server client不想消費這個消息廉羔。server然后發(fā)送這個消息給另外的client,丟棄它或者把它放在無效的消息隊列中。這種準確的行為是server特定的僻造。

NACK有相同的ACKheaders:id(必選)和transaction(可選)憋他。

NACK適用于單個消息(訂閱的ack模式為client-individual), 或者那些還沒有被ACK'ed和NACK'ed的消息(訂閱模式ack為client).

BEGIN

BEGIN用于事務的開始。事務被用于發(fā)送和確認消息髓削,被發(fā)送和被確認的消息在事務過程中會被自動處理竹挡。

BEGIN

transaction:tx1

^@

transactionheader是必填的,并且事務id將被用于在SEND, COMMIT, ABORT, ACK, and NACK frames去綁定命名的事務.在相同的連接中立膛,不同事務必須用不同的id

如果client發(fā)送DISCONNECTframe或者TCP連接失敗揪罕,任何已開始但沒有提交的事務默認都會被中斷.

COMMIT

COMMIT用于在過程中提交事務.

COMMIT

transaction:tx1

^@

transactionheader是必填的并且必須指定將要提交的事務的id.

ABORT

ABORT用于在過程中回滾事務.

ABORT

transaction:tx1

^@

transactionheader是必填的并且必須指定將要提交的事務的id.

DISCONNECT

client能在任何時候斷開server的連接,但是不能保證已經(jīng)發(fā)送的frame已經(jīng)到達了server梯码。為了讓這一切顯得不那么暴力,client確保所有已經(jīng)發(fā)送的frames已經(jīng)被server收到好啰,client應該做以下3點:

發(fā)送帶有receiptheader的DISCONNECTframe

DISCONNECT

receipt:77

^@

等待帶有RECEIPTframe的響應

RECEIPT

receipt-id:77

^@

關(guān)閉socket

注意轩娶,如果server過早地關(guān)閉socket,client將不會收到期望地RECEIPTframe.見Connection_Lingering

client發(fā)送DISCONNECTframe后不必要在發(fā)送任何frame.

Server Frames

server偶爾也會發(fā)送frame給客戶端(除了連接最初的CONNECTEDframe).

這些frames為: *MESSAGE*RECEIPT*ERROR

MESSAGE

MESSAGEframe用于將訂閱的消息發(fā)送給client.

MESSAGEframe必須包含destinationheader表明信息要到達的目的地框往。如果消息已經(jīng)用STOMP發(fā)送鳄抒,那么destinationheader應該和SENDframe中的一樣。

MESSAGEframe必須包含帶有唯一標識的message-idheader和帶有將接收消息的訂閱的idsubscriptionheader.

如果從訂閱收到的消息需要明確作出確認(client或者client-individual模式),那么MESSAGEframe必須包含帶有任何值的ackheader.這個header將把消息和后來的ACK,NACKframe關(guān)聯(lián)起來椰弊。

下面這個frame body包含了消息的內(nèi)容:

MESSAGE

subscription:0

message-id:007

destination:/queue/a

content-type:text/plain

hello queue a^@

如果frame body包含內(nèi)容的話许溅,MESSAGEframe應該包含content-lengthheader和content-typeheader.

除了那些server指定的headers, 消息被發(fā)送到目的地時,MESSAGEframe同樣應該包括所有用戶定義的headers.查閱有關(guān)文檔秉版,找出那些server指定添加到messages的headers.

RECEIPT

server成功處理請求帶有receipt的client frame后贤重, 將發(fā)送RECEIPTframe到client.RECEIPTframe必須包含receipt-idheader,它的值為client frame中receiptheader的值。

RECEIPT

receipt-id:message-12345

^@

RECEIPTframe是作為server處理的client frame后的應答. 既然STOMP是基于流的清焕,那么receipt也是對server已經(jīng)收到所有的frames的累積確認游桩。但是,以前的frames可能并沒有被完全處理耐朴。如果clients斷開連接,以前接收到的frames應該繼續(xù)被server處理盹憎。

ERROR

如果出錯的話筛峭,server將發(fā)送ERRORframe.這種情況下,server還應該斷開連接陪每。查看下一章connection lingeringERRORframe應該包含帶有簡單錯誤信息的messageheader,或者Body包含詳細的描述信息影晓,也可能沒有。

ERROR

receipt-id:message-12345

content-type:text/plain

content-length:171

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.

^@

如果錯誤關(guān)聯(lián)到了具體的某個client frame檩禾,那么server應該增加額外的headers去識別引起錯誤的frame挂签。例如,如果frame包含receiptheader,ERRORframe應該設置receipt-idheader的值為引起錯誤的frame的receiptheader的值。

如果frame body包含內(nèi)容的話盼产,ERRORframe應該包含content-lengthheader和content-typeheader

Frames and Headers

除了上述標準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 ,它們會成為carried message的一部分戏售。同樣侨核,ERRORframe應該包含額外的headers來識別引起錯誤的frame。

最終灌灾,STOMP servers可以用額外的headers去訪問持久化或者有效期特性.查閱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? ? ? ? ? ? ? ? =

LF? ? ? ? ? ? ? ? ? =

CR? ? ? ? ? ? ? ? ? =

EOL? ? ? ? ? ? ? ? = [CR] LF

OCTET? ? ? ? ? ? ? =

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*

header-value? ? ? ? = *

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個濱河市锋喜,隨后出現(xiàn)的幾起案子些己,更是在濱河造成了極大的恐慌豌鸡,老刑警劉巖,帶你破解...
    沈念sama閱讀 218,941評論 6 508
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件段标,死亡現(xiàn)場離奇詭異涯冠,居然都是意外死亡,警方通過查閱死者的電腦和手機怀樟,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 93,397評論 3 395
  • 文/潘曉璐 我一進店門功偿,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人往堡,你說我怎么就攤上這事械荷。” “怎么了虑灰?”我有些...
    開封第一講書人閱讀 165,345評論 0 356
  • 文/不壞的土叔 我叫張陵吨瞎,是天一觀的道長。 經(jīng)常有香客問我穆咐,道長颤诀,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 58,851評論 1 295
  • 正文 為了忘掉前任对湃,我火速辦了婚禮崖叫,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘拍柒。我一直安慰自己心傀,他們只是感情好,可當我...
    茶點故事閱讀 67,868評論 6 392
  • 文/花漫 我一把揭開白布拆讯。 她就那樣靜靜地躺著脂男,像睡著了一般。 火紅的嫁衣襯著肌膚如雪种呐。 梳的紋絲不亂的頭發(fā)上宰翅,一...
    開封第一講書人閱讀 51,688評論 1 305
  • 那天,我揣著相機與錄音爽室,去河邊找鬼汁讼。 笑死,一個胖子當著我的面吹牛阔墩,可吹牛的內(nèi)容都是我干的掉缺。 我是一名探鬼主播,決...
    沈念sama閱讀 40,414評論 3 418
  • 文/蒼蘭香墨 我猛地睜開眼戈擒,長吁一口氣:“原來是場噩夢啊……” “哼眶明!你這毒婦竟也來了?” 一聲冷哼從身側(cè)響起筐高,我...
    開封第一講書人閱讀 39,319評論 0 276
  • 序言:老撾萬榮一對情侶失蹤搜囱,失蹤者是張志新(化名)和其女友劉穎丑瞧,沒想到半個月后,有當?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體蜀肘,經(jīng)...
    沈念sama閱讀 45,775評論 1 315
  • 正文 獨居荒郊野嶺守林人離奇死亡绊汹,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 37,945評論 3 336
  • 正文 我和宋清朗相戀三年,在試婚紗的時候發(fā)現(xiàn)自己被綠了扮宠。 大學時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片西乖。...
    茶點故事閱讀 40,096評論 1 350
  • 序言:一個原本活蹦亂跳的男人離奇死亡,死狀恐怖坛增,靈堂內(nèi)的尸體忽然破棺而出获雕,到底是詐尸還是另有隱情,我是刑警寧澤收捣,帶...
    沈念sama閱讀 35,789評論 5 346
  • 正文 年R本政府宣布届案,位于F島的核電站,受9級特大地震影響罢艾,放射性物質(zhì)發(fā)生泄漏楣颠。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點故事閱讀 41,437評論 3 331
  • 文/蒙蒙 一咐蚯、第九天 我趴在偏房一處隱蔽的房頂上張望童漩。 院中可真熱鬧,春花似錦春锋、人聲如沸矫膨。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,993評論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至直奋,卻和暖如春能庆,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背脚线。 一陣腳步聲響...
    開封第一講書人閱讀 33,107評論 1 271
  • 我被黑心中介騙來泰國打工搁胆, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留,地道東北人邮绿。 一個月前我還...
    沈念sama閱讀 48,308評論 3 372
  • 正文 我出身青樓渠旁,卻偏偏與公主長得像,于是被迫代替她去往敵國和親船逮。 傳聞我的和親對象是個殘疾皇子顾腊,可洞房花燭夜當晚...
    茶點故事閱讀 45,037評論 2 355

推薦閱讀更多精彩內(nèi)容