1

ejabberd を使用する iOS でインスタント メッセンジャー アプリを構築しています。私は現在、ストリーム管理機能と、特にほとんどの場合に機能するように見える再開をテストしています。ただし、設定を考慮して、次の手順で複製できることを理解できない場合があります: resume_timeout: 30, resend_on_timeout: if_offline

  • 最初にクライアント A とクライアント B が接続され、他のリソースは接続されていません
  • クライアント B がクリーンでない方法でクラッシュまたは切断する
  • クライアント A は大量のメッセージ (10 件以上) を非常に迅速に送信し始めます
  • ejabberd は、メッセージがサーバーに到達したことを確認するために、送信された各メッセージに対して ack を A に送信します。
  • クラッシュから約 20 秒後、B は再接続します。この時点で、A は以前に送信された各メッセージのエラーを受け取ります。
<message xmlns="jabber:client" from="clientB@mydomain" to="clientA@mydomain/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 に正しく配信されることがあります。

私の質問は次のとおりです。

  • この動作は正しいですか?メッセージの ack が既に受信されている場合、クライアント A にエラーが返されないことが期待されます。
  • resend_on_timeout設定されてif_offlineおり、他のリソースが接続されていないため、エラーはまったくないと予想されます。私は正しいですか?
4

2 に答える 2

2
  • Stream Management ack は、サーバーがメッセージを受信したことのみを示します。メッセージが処理されたこと、または指定されたアドレスに配信されたことを意味するものではありません。アドレスに配信された場合でも、そのデバイスはスタンザのエラーを返す可能性があります。
  • これは実際には単なる一刺しにすぎませんが、ejabberd コードをざっと見てみると、次のようになる可能性があります。

    1. clientB@mydomain/ResourceBが接続を切断すると、現在、 を使用して再開を待っているセッションがありResourceBます。
    2. クライアント B は再接続しますが、再開しません (クラッシュして状態が失われたため)。
    3. ResourceBクライアント B がリソースを再度バインドします。
    4. ここで、クライアント B が同じリソースを要求したため、サーバーは再開を待っていたスリープ セッションを終了する必要があります。
    5. に設定されているため、サーバーは他のセッションがあるかどうかをチェックしますif_offline
    6. サーバーはセッション (新しいセッション) があることを認識し、再送信ではなくバウンスを選択します。

    したがって、私の理論はif_offline、メッセージが最初に受信されたときではなく、未確認メッセージのキューを処理する必要があるときにのみ、他のセッションがあるかどうかを確認するというものです。

于 2016-02-02T13:47:18.177 に答える
1

@xnyhps の応答は正しく、次の ejabberd リリースのためにこの特定のコーナー ケースを修正しました。ただし、@xnyhpsは、他のコーナーケースがあることも正しいため、信頼できるメッセージ配信が必要な場合は、XEP-0313 を使用する必要があります。XEP-0198 の主な機能は、セッションの再開です。

于 2016-02-06T23:17:07.797 に答える