asmack實現端到端的消息回執(XEP-0184: Message Delivery Receipts)


要想保證信息的傳輸,目前在smack/asmack + openfire架構上,我個人想到有兩種實現方式:


1.端到端確保發送(類似短信)。

其實這個就是xmpp協議的XEP-0184: Message Delivery Receipts.

裏邊爲了確保消息的到達,需要接收方返回回執,這樣發送方就知道對方是否確切收到消息。

當然咯,接收回執過程中也可能出現斷線,導致發送方收不到回執,而認爲接收方沒收到,再重新發的問題,這個需要接收方過濾掉重複的信息來解決。

其實這個協議,asmack在0.8.3版本就已經支持,具體什麼版本開始,就懶得去研究了。

需要注意的是:這個是兩個客戶端之間的事情,即openfire什麼也不用幹,只要客戶端都支持xep-0184就可以了。

 

下面簡單說下xep-0184協議的交互內容:

發送方發送一個需要回執的消息:

[plain] view plaincopy
  1. <message from='[email protected]/westminster'  
  2.                     id='richard2-4.1.247'  
  3.                     to='[email protected]/throne'>  
  4.     <body>My lord, dispatch; read o'er these articles.</body>  
  5.     <request xmlns='urn:xmpp:receipts'/>  
  6. </message>  

 

接收方收到消息後,返回的消息:

[plain] view plaincopy
  1. <message from='[email protected]/throne'  
  2.                 id='bi29sg183b4v'  
  3.             to='[email protected]/westminster'>  
  4.     <received xmlns='urn:xmpp:receipts' id='richard2-4.1.247'/>  
  5. </message>  


注意回執的id要與接收的packetID對應。

 

好了,瞭解原理了。大家來看看asmack是怎麼實現的。

http://bamboo.igniterealtime.org/browse/SMACK-TRUNK-59/commit 上說的好簡單,實際上你不會成功的,因爲asmack有bug抓狂,目前最新的0.8.5上也沒解決。

下面跟大家介紹怎麼使用消息回執及解決這個bug。奮鬥

 

發送需要回執的消息前,調用

[java] view plaincopy
  1. DeliveryReceiptManager.addDeliveryReceiptRequest(packet);  
  2. myConnection.sendPacket(packet);  

來爲你的packet添加<request xmlns='urn:xmpp:receipts'/>節點。

 

在初始化xmppconnection後,調用

[java] view plaincopy
  1. DeliveryReceiptManager.getInstanceFor(myConnection)  
  2.              .enableAutoReceipts();  

來設置自動進行回執,設置後,回執的事情就不用我們自己操心啦。

好了,要做的事情就這麼點。額,尷尬,,本來應該就這麼點。但是。。asmack有bug啊發火,他把request跟received都用同一個ExtensionProvider啦!!

證據在org.jivesoftware.smackx.ConfigureProviderManager類裏邊這兩句:

[java] view plaincopy
  1. // XEP-184 Message Delivery Receipts  
  2. pm.addExtensionProvider("received""urn:xmpp:receipts"new DeliveryReceipt.Provider());  
  3. pm.addExtensionProvider("request""urn:xmpp:receipts"new DeliveryReceipt.Provider());  

都用了同一個Provider,當然出問題了。就是接受者無法找到<request xmlns='urn:xmpp:receipts'/>節點,因爲DeliveryReceipt.Provider()生成的是received節點。

於是乎,自動回執沒有效果。

“改吧!。。”

“不改jar包行不行啊?”

“行啊!”

如下:

[java] view plaincopy
  1. sAndroid = SmackAndroid.init(cxtContext);  
  2. ProviderManager pm = ProviderManager.getInstance();  
  3. // add delivery receipts  
  4. pm.addExtensionProvider(DeliveryReceipt.ELEMENT, DeliveryReceipt.NAMESPACE,  
  5.         new DeliveryReceipt.Provider());  
  6. pm.addExtensionProvider(DeliveryReceiptRequest.ELEMENT, DeliveryReceipt.NAMESPACE,  
  7.         new DeliveryReceiptRequest.Provider());  


將jar包中錯誤的設置,重新設置一下。這樣,消息回執功能就大功告成啦。。

xep-0184裏邊還講了如何判斷客戶端是否支持消息回執的問題,如果你有這樣的需求,就自己去了解吧。


2.openfire服務端確保消息發送到達(待續)

我不知是否是由於MINA太舊的原因,導致openfire在nio發送的過程中,無法捕獲發送異常,導致無法識別異常斷線的客戶端,也就不能準確的保存離線消息。
openfire目前用的MINA是1.1.7版本,可能是這個版本有問題。apache在這版本上進行了重大的調整和改造,版本號直接改成2.0.0。因此直接升級openfire的MINA包難度很大,連openfire開發者們都拖了這麼些年不更新MINA版本。。

這個原因純屬個人猜測,於是這個方法走不通。有興趣的同學可以試試,熟悉MINA的人應該能看出來。

 

既然底層機制不可變,那就只能通過自己的手法來處理了。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章