QQ討論羣:172158202
html
轉載原文地址:http://blog.csdn.net/yuedong56/article/details/38120101
ios
xep-0198英文文檔連接地址:點擊打開連接
RFC 6120中文連接地址:點擊打開連接算法
相關參考1:點擊打開連接
網絡
Stream management是在XML流的標準上使用的。檢查一個給定的流TCP的連通性的時候。特別推薦使用whitespace keepalives(見RFC 6120)、XMPP Ping (XEP-0199) 或者TCP keepalives。對照Stream management,高級消息處理Advanced Message Processing (XEP-0079)和消息回執Message Delivery Receipts (XEP-0184)。定義了ack,它可以經過多個流實現端對端的傳輸;這些特性在一些特殊狀況中是實用的,但是不是必需去檢查在兩個xmpp實體之間直接傳遞的流。
注:Stream management可以用於服務端到服務端、client到服務端的流。但是,爲了方便,本規範僅僅討論client到服務端的流。session
相同的原則也適用於server到server的流。(在本文檔中,以「C:」開頭的都是由client發送的,由「S:「開頭的都是由server發送的)。
2. 流特性(Stream Feature)
服務端返回一個流的header給client,緊接着要發送流的features。這些features包含一個<sm/>元素「urn:xmpp:sm:3」的命名空間namespace(見Namespace Versioning 關於版本添加的可能性)。
注:client不能negotiate(談判,商量;轉讓;越過) stream management,除非client已經身份驗證並且綁定了一個資源。見如下的特定的限制條件。
例1:server發送新的流的header和流的features。
dom
S: <stream:stream from='example.com' xmlns='jabber:client' xmlns:stream='http://etherx.jabber.org/streams' version='1.0'> S: <stream:features> <bind xmlns='urn:ietf:params:xml:ns:xmpp-bind'/> <sm xmlns='urn:xmpp:sm:3'/> </stream:features>3. 啓動Stream Management
C: <enable xmlns='urn:xmpp:sm:3’/>假設client想被贊成恢復流,必須包含一個boolean類型的「resume」屬性。默以爲false。恢復先前的一個會話(section),請參閱本文檔的恢復部分。
<failed/>元素表示在創建stream management 會話(session)中存在一個問題。ide
<enabled/>元素表示成功的創建了stream management 會話。
例3:服務端啓動stream management
工具
S: <enabled xmlns='urn:xmpp:sm:3’/>而後可以使用stream management的特性定義如下的內容。
假設服務端贊成會話恢復。服務端必須包含一個resume屬性。值爲」ture「或者」1「。性能
例4:服務端啓動贊成會話恢復的stream management
優化
S: <enabled xmlns='urn:xmpp:sm:3' id='some-long-sm-id' resume='true’/><enabled/>元素可以包括一個」max「屬性,用來指定服務端特定的最大恢復時間。
client不能嘗試negotiate stream management,除非經過了身份驗證;也就是說client不能發送一個<enabled/>元素直到完畢了身份驗證。(好比,SASL,Non-SASL Authentication (XEP-0078)或者 Server Dialback (XEP-0220)已經成功完畢)。
對於client到服務端的鏈接。在沒有完畢資源綁定前,client禁止啓動流管理,除非正在恢復一個以前的會話(見Resumption)。
服務端應該實施這個命令,假設這個規則被違反了。要返回一個<fail/>元素。
S: <failed xmlns='urn:xmpp:sm:3'> <unexpected-request xmlns='urn:ietf:params:xml:ns:xmpp-stanzas'/> </failed>
4. Acks
啓動流管理(stream management)以後,client或者服務端可以在隨意時間經過流發送ack元素。ack元素可以是:
<a/>元素用於回答一個確認收到的請求或者發送一個未被請求的ack。
<r/>元素用於請求收到節(stanzas)的確認信息。
屬性定義例如如下:
'h'屬性標識最後處理的節(即,server確認收到最後一節)。
一個<a/>元素必須具有一個」h「屬性。
<r/>元素沒有已定義屬性。
定義:確認一條以前收到的ack元素。節是被server處理後再發送出去的。對於服務端的處理,咱們是指服務端接管一條或多條節(如。直接處理節。將節傳給本地的一個實體。比方一樣server下的還有一個client,或者將節發送給其它server的遠程實體);一個節在確認被服務端處理以前,發送方都要對節負責(好比,假設沒有被服務端確認處理。client要重發這個節或者生成一個錯誤)。
收到一個<r/>元素的回執並不意味着新的節已經傳送給對方,僅僅有收到一個<a/>元素的回執。並且包括「h」屬性已經增加了,才說明這個新的節已經被處理過。
「h」值在流管理中被啓動或被請求啓動時,是從零開始的。當第一個節被處理的時候,「h」值添加爲1。並隨着接下來新的節被處理,「h」值不斷添加。在一些極端狀況下,在流管理對話中被處理的節的數量,超出了無符號整型數所表示的最大數(2的32次方)XML Schema Part 2 [10],「h」值應該被置爲0,而不是2的32次方。
注意:不論什麼給定的流,都有兩個「h」值。一個被client用於跟蹤節是否被服務端處理,還有一個被服務端用於跟蹤節是否被處理自client。當client向服務端發送<enable/>時,client初始化它的「h」值爲零,相同服務端發送<enable/>給client時,也初始化它的「h」值爲零(服務端會立刻回覆<enable/>,同一時候設置它的計數器爲零)。初始化後。client依據處理的節的數目不斷添加「h」值,服務端也對應不斷添加「h」值。
如下的帶凝視的樣例。包含client發的一段消息。一個確認接收的請求,一個節的ack。
例6:Simple stanza acking
C: <enable xmlns='urn:xmpp:sm:3'/> <!-- Client sets outbound count to zero.(client設置outbound爲0) --> C: <message from='laurence@example.net/churchyard' to='juliet@example.com' xml:lang='en'> <body> I'll send a friar with speed, to Mantua, with my letters to thy lord. </body> </message> <!-- Note that client need not wait for a response.(注意client不需要等待回覆) --> S: <enabled xmlns='urn:xmpp:sm:3'/> <!-- Server receives enable, and responds, setting both inbound and outbound counts to zero. (服務端接收enable,回覆client,設置inbound和outboard數爲零) In addition, client sets inbound count to zero. (另外,client設置inbound爲零) --> C: <r xmlns='urn:xmpp:sm:3'/> S: <a xmlns='urn:xmpp:sm:3' h='1'/>當一個<r/>元素(「request」)被收到時。接收方必須經過給發送方發送一個帶h值的<a/>元素的回執確認,h值大小爲<r/>元素接受方處理的節的數量。
回覆必須在接收到<r/>元素後立刻發送。除了超時之外的不論什麼狀況,都不能保留。好比,有時候client的網速比較慢,它在確認收到前可能但願在一段時間內收集很是多節,服務端可能但願下降傳入的節。
發送方無需等待繼續發送節的ack。
不論什麼一方都可以在不論什麼時間發送一條<a/>元素(如。接收完確切數目的節後。或者一個肯定的時間段事後),即使是未收到對方發送的<r/>元素。
當一方收到一個<a/>元素,必須返回一個h值做爲當前流最後處理的那條出站節(outbound stanza)的序列號。
假設一個流結束了,也沒有在<enable/>元素中指定的時間內恢復。序列號和不論什麼相關的狀態都可以被兩方丟棄。
在會話狀態被丟棄前,應該對不論什麼未處理的節(即在收到近期的h值後發送的節)採取替代措施。
*服務端應該採用一樣的方式處理未確認的節。對於發送到不可用資源的節,服務端應該給發送方返回一個錯誤。或者把該節提交給離線倉庫存儲。
*面向用戶的client應該悄悄地(不用通知用戶)經過鏈接又一次發送節,或者經過一個合適的交互方式通知用戶發送失敗。
因爲未被確認收到的節可能已經被對方接收,重發有可能致使反覆發送。雖然至少可以經過每個節的id協助接收方排除反覆接收的節,但是該協議還沒法預防這樣的狀況的發生。
5. 恢復
xml流有可能發生意外終止(如,因爲網絡中斷)。這樣的狀況需要迅速的恢復以前的流,而不是完畢流的新建,花名冊的檢索和狀態的播送。
另外。該協議會在先前的鏈接中交換最後收到的流的序列號,贊成實體終於肯定哪些節需要重發,哪些節不需要重發,經過重放消除反覆。
請求中流都是可恢復的,當開啓流管理時,client必須給<enable/>元素添加一個「resume」屬性,它的值可以是「true」或者「1」。
例7:client開啓流管理
C: <enable xmlns='urn:xmpp:sm:3' resume='true’/>要贊成流被恢復,服務端必須在<enable/>元素中包括一個「resume」屬性,設爲ture或者1;必須包括一個「id」屬性,用於做爲流的標識符。
S: <enabled xmlns='urn:xmpp:sm:3' id='some-long-sm-id' resume='true’/>定義:id屬性爲流管理定義了一個惟一標識(「SM-ID」)。SM-ID必須由服務端生成。client必須認定SM-ID是一個不透明的類型,所以不一樣意分配給SM-ID不論什麼語義。
服務端可以編碼不論什麼它以爲實用的信息。如full JID<localpart@domain.tld/resource>。賦給SM-ID(如full JID拼上一個當前的屬性)。不論什麼在XML中被贊成的字符屬性都是可用的。
SM-ID不一樣意被當前和之後的會話重用(但是server不需要確保SM-ID一直是惟一的。僅僅有在server繼續執行的時候)。SM-ID不該該超過4000個字節。
如上所述,<enable/>元素可以包括一個「location」屬性,用於指明重連的首選位置(如。一個爲已經聯網的client保存狀態的特定的連接管理器)。
例9:server會選擇在一個特定的位置又一次連接
S: <enabled xmlns='urn:xmpp:sm:3' id='some-long-sm-id' location='[2001:41D0:1:A49b::1]:9222' resume='true’/>假設流意外中止了。client就會向server開一個TCP連接。所有事件的順序例如如下:
5.client發送 STARTTLS 請求。
6.服務端通知client繼續進行TLS協議。
7.兩方完畢一次TLS握手(注意:假設正在進行恢復會話,同一時候也在用TLS,建議利用TLS會話恢復RFC5077,進一步優化XML流的恢復)。
8.client發送新初始化的流的header。
9.服務端向client回覆流的header。
10.服務端向client發送流的features,要求SASL協議。提供合適的SASL機制(注意:假設服務端以爲在TLS會話恢復中提供的信息足夠的真實可信,它可以提供SASL EXTERNAL 機制;詳細的請參考draft-cridland-sasl-tls-sessions [13])。
11.兩方完畢SASL協議。
12.client發送新初始化的流的header。
13.服務端向client回覆流的header。
14.服務端發送流的features,提供SM的features。
15.client請求恢復以前的流。
注意:這些事件的順序也可能以上的順序。取決於服務端提供SM features的時間,client是否選擇STARTTLS。等等。另外,其實服務端到服務端的流經常沒有完畢SASL協議,甚至也不完畢TLS協議。
上面講的並無改變RFC6120中規定的有關流協議的不論什麼規則。而後,因爲流管理適用於xml節(不是不論什麼其它xml元素)的交換,這使得當可能要開始向還有一方發送節的時候(不是以前)。服務端提供SM features變得有意義。
見Recommended Order of Stream Feature Negotiation (XEP-0170) [14]。
請求恢復以前已經終止的流。client要發送一個<resume/>元素,附上「urn:xmpp:sm:3」的命名空間。<resume/>元素必須包括一個「previd」屬性。該屬性的值爲要恢復的流的SM-ID,還有包括一個h值,該值標識經過要恢復的流。服務端發送給client的最後一個被處理的節的序列號(萬一client沒有收到不論什麼的節。它將設置h值爲0)。
例10:流恢復請求
C: <resume xmlns='urn:xmpp:sm:3' h='some-sequence-number' previd='some-long-sm-id’/>假設server能恢復以前的流,必須返回一個<resumed/>元素。該元素必須包括一個「previd」屬性。值爲要恢復的流的SM-ID,還有必須包括一個h值。值爲該值標識經過要恢復的流,client發送給服務端的最後一個被處理的節的序列號(萬一服務端沒有收到不論什麼的節,它將設置h值爲0)。
例11:被恢復的流
S: <resumed xmlns='urn:xmpp:sm:3' h='another-sequence-number' previd='some-long-sm-id’/>假設服務端不支持會話恢復,必須返回一個<failed/>元素,該元素要包括一個<feature-not-implemented/>的錯誤條件。假設服務端沒有把「previd」識別爲一個更早的會話(好比,可能因爲以前的會話已經超時),也必須返回一個<failed/>元素,該元素必須包括一個<item-not-found/>的錯誤條件。在這兩種失敗的狀況中。server都應該贊成client在這時綁定一個資源,而不是強制client又一次開始流協議處理過程和又一次認證。
假設以前的流恢復了,此時服務端還依舊保持着以前認證過(previously-identified)的會話開着,應該終止以前的流。
當一個會話被恢復時。兩方處理步驟例如如下:
*序列值沿用了以前會話的,而且不會被新的流改動。
*一旦收到<resume/>或者<resumed/>元素,client和服務端利用h值又一次發送所有因爲斷開鏈接而丟失的節。其實。應該處理這倆元素的h值,就像在<a/>元素中處理它同樣(即,在發出隊列中標記節爲已經被處理),除此以外,必須將不論什麼仍被標記爲未處理的節又一次發送給對方。
*兩方都應該重發在先前的對話中未被標記處理的節,重發時是依據對方記錄的序列號。
*正在重連的client不能請求花名冊,因爲在client斷開鏈接的過程當中不論什麼花名冊信息的改變都會在流管理會話恢復後被髮送給client。
*client不能在其試圖恢復以前presence狀態的時候發送presence節。因爲這個狀態可能已經被服務端保存。
*兩方都不能試圖重建狀態信息(如。Service Discovery (XEP-0030) [15] information)。
6.錯誤處理
假設對於一個<enable/>或者<resume/>元素。假設出現了錯誤。server必須返回一個<failed/>元素。這個元素要包括一個錯誤條件。它必須是RFC6120裏定義的所有節錯誤條件中的一個。
如下是個樣例。
例12:服務端返回錯誤
S: <failed xmlns='urn:xmpp:sm:3'> <unexpected-request xmlns='urn:ietf:params:xml:ns:xmpp-stanzas'/> </failed>流管理錯誤被以爲是可恢復的。但是,錯誤的使用流管理可能會致使流的終止。
在離開一個未完畢狀態的流以前,client可以發送不論什麼但願的presence信息。
8.情景(Scenarios)
如下的幾種情景列舉了幾種不一樣的流管理的使用。這些樣例都是關於client和服務端之間的,但是流管理還可以用於服務端對對服務端的流。
8.1 主要的acking情景
流管理協議可以經過acks,在沒有恢復會話的能力的條件下提升可靠性。
一個主要的實現將運行下面操做:
*做爲一個client,發送不帶不論什麼屬性的<enable/>。不用管在<enable/>回覆中的屬性。
未完待續。。。