2016-02-02 41 views
1

我在使用ejabberd的iOS上構建即時通訊應用程序。我目前正在測試流管理功能,特別是在大多數情況下似乎可以使用的恢復功能。然而,有我不理解的情況下,我可以通過以下步驟進行復制,同時在賬戶設置:resume_timeout:30,resend_on_timeout:if_offlineejabberd中的流管理奇怪的錯誤

  • 一開始客戶A和客戶B連接,沒有其他的資源被連接
  • 客戶端B崩潰或斷開在不乾淨的方式
  • 客戶端A開始發送一束信息(10+)很快
  • ejabberd發送ACK到一種用於發送到每個消息確認消息到達服務器
  • a自墜毀後20秒,B重新連接。在這個時刻A接收之前
<message xmlns="jabber:client" from="[email protected]" to="[email protected]/resourceID" type="error" id="CFBF4583-209A-4453-2567-CCCC7894827E"> 
    <body>test</body> 
    <active xmlns="http://jabber.org/protocol/chatstates" /> 
    <request xmlns="urn:xmpp:receipts" /> 
    <error code="503" type="cancel"> 
     <service-unavailable xmlns="urn:ietf:params:xml:ns:xmpp-stanzas" /> 
    </error> 
</message> 

我與ejabberd 16.01試圖爲每個消息的錯誤發送。

這發生在80%的時間;有時由A發送的消息在30秒內被正確傳遞給B重新連接。

我的問題是:

  • 是這種行爲是否正確?我希望如果已經收到一條消息的確認信號,就不會向客戶端A返回錯誤。
  • 由於resend_on_timeout設置爲if_offline並且沒有其他資源連接,我預計根本沒有錯誤。我對麼?

回答

2
  • 流管理acks只表明消息已被您的服務器接收。這並不意味着郵件已被處理或傳送到指定的地址。即使它已發送到地址,那麼該設備仍可爲該節返回錯誤。
  • 這真的只是在黑暗中刺,但有過ejabberd代碼一眼後,這可能是發生了什麼:

    1. [email protected]/ResourceB降低它們的連接,現在有一個會話等待復課使用ResourceB
    2. 客戶端B重新連接,不會恢復(因爲它崩潰並丟失其狀態)。
    3. 客戶端B再次綁定資源ResourceB
    4. 現在服務器必須終止正在等待恢復的睡眠會話,因爲客戶端B請求相同的資源。
    5. 服務器檢查是否有其他會話,因爲它設置爲if_offline
    6. 服務器看到有一個會話(新會話),因此選擇反彈而不是重發。

    所以我的理論是,if_offline只檢查是否有其他會議時,未確認消息的隊列需要處理,而不是在消息最初收到時。

+0

這絕對有道理。對於ejabberd來說,在這種特殊情況下檢查資源並重新發送消息而不是將錯誤發送給發件人是不可取的? – theMoonlitKnight

+0

@theMoonlitKnight XEP-0198有很多邊緣情況可能會丟失信息。如果您想確保獲得全部信息,則應使用XEP-0313將消息存儲在服務器上,然後檢索它們。 – xnyhps

1

@xnyhps的迴應是正確的,我fixed這個特殊的角落情況下一個ejabberd釋放。然而,@ xnyhps也是正確的,還有其他的角落案例,所以如果你想要可靠的消息傳遞,你應該使用XEP-0313。 XEP-0198的主要特點是會話恢復。