gloox-心跳包-xmpp

来源:互联网 发布:淘宝网爱奇艺会员 编辑:程序博客网 时间:2024/05/16 10:50
改定履历:

2011-08-25-----------新建文本文档

通常在客户端与服务器之间需要心跳来维系连接,XMPP可以通过一个扩展协议XEP-0199来实现客户端与服务器端的心跳。XEP-0199规定通过发送命名空间为'urn:xmpp:ping'的iq节XML流来解决这个问题。本文代码为测试代码……

本文阐述GLOOX客户端对服务器消息的封装

客户端向服务器发送ping消息:

[html] view plaincopy
  1. <iqfrom='juliet@capulet.lit/balcony'to='capulet.lit'id='c2s1'type='get'> <ping xmlns='urn:xmpp:ping'/></iq> 
[html] view plaincopy
  1. <iq from='juliet@capulet.lit/balcony' to='capulet.lit' id='c2s1' type='get'>  <ping xmlns='urn:xmpp:ping'/></iq>  

服务器的响应pong:

[html] view plaincopy
  1. <iq from='capulet.lit' to='juliet@capulet.lit/balcony' id='c2s1' type='result'/> 
[html] view plaincopy
  1. <iq from='capulet.lit' to='juliet@capulet.lit/balcony' id='c2s1' type='result'/>  


如果服务器不支持ping命名空间,则必须要返回一个<service-unavailable/> 的error:

[html] view plaincopy
  1. <iq from='capulet.lit' to='juliet@capulet.lit/balcony' id='c2s1' type='error'>  <ping xmlns='urn:xmpp:ping'/>  <errortype='cancel'>    <service-unavailable xmlns='urn:ietf:params:xml:ns:xmpp-stanzas'/>  </error></iq> 
[html] view plaincopy
  1. <iq from='capulet.lit' to='juliet@capulet.lit/balcony' id='c2s1' type='error'>  <ping xmlns='urn:xmpp:ping'/>  <error type='cancel'>    <service-unavailable xmlns='urn:ietf:params:xml:ns:xmpp-stanzas'/>  </error></iq>  


封装思路:

在程序中另起一个线程专门用做心跳处理;GLOOX库里对XEP-0199的ping发送实现是在ClientBase类里的一个方法:

void xmppPing(const JID &to,  EventHandler *eh )

在说明这个方法之前先介绍GLOOX里面几个相关的类:

ClientBase : 这个类里面用一个方法xmppPing实现XEP-0199 ping消息发送。

EventHandler : ping事件处理器,观察者,纯虚基类。实现其虚函数可以收到Ping响应时得到处理。

EventDispatcher : ping事件分发器,用于注册及注销EventHandler。

Event : ping事件封装类。

方法说明:Sends a XMPP Ping (XEP-0199) to the given JID. 即发送一个符合xep-0199规范的ping消息给指定的JID。我们这里是做对服务器的心跳,所以这里的JID就是服务器的JID;EventHandler是观察者(设计模式之观察者模式),在xmppPing的实现里会将会由EventDispatcher对象将观察者注册进去,在得到事件时将由EventDispatcher将事件分发给观相应的察者处理。所以我们要实现观察者EventHandler.

观察者实现:

[cpp] view plaincopy
  1. class CEventHandler:public EventHandler 
  2. public
  3.     CEventHandler(); 
  4.     virtual ~CEventHandler(); 
  5.     virtual void handleEvent(const Event& event); 
  6.     void increaceHeartBeatCount(void); 
  7.     UINT getHeartBeatCount(){return m_nCount;} 
  8. private
  9.     void decreaceHeartBeatCount(void); 
  10.     UINT m_nCount; 
  11. }; 
[cpp] view plaincopy
  1. class CEventHandler:public EventHandler  
  2. {  
  3. public:  
  4.     CEventHandler();  
  5.     virtual ~CEventHandler();  
  6.     virtual void handleEvent(const Event& event);  
  7.     void increaceHeartBeatCount(void);  
  8.     UINT getHeartBeatCount(){return m_nCount;}  
  9. private:  
  10.     void decreaceHeartBeatCount(void);  
  11.     UINT m_nCount;  
  12. };  

[cpp] view plaincopy
  1. CEventHandler::CEventHandler():m_nCount(0) 
  2.  
  3.  
  4. CEventHandler::~CEventHandler() 
  5.  
  6.  
  7. void CEventHandler::increaceHeartBeatCount() 
  8.     m_nCount++; 
  9.     return
  10.  
  11. void CEventHandler::decreaceHeartBeatCount() 
  12.     if (m_nCount > 0) 
  13.     { 
  14.         m_nCount--; 
  15.     } 
  16.     return
  17.  
  18. void CEventHandler::handleEvent(const Event& event) 
  19.     std::string sEvent; 
  20.     switch (event.eventType()) 
  21.     { 
  22.     case Event::PingPing:   //! 收到PING消息 
  23.         sEvent = "PingPing"
  24.         break
  25.     case Event::PingPong:   //! 收到返回PONG消息,心跳累计次数减1 
  26.         sEvent = "PingPong"
  27.         decreaceHeartBeatCount(); 
  28.         break
  29.     case Event::PingError:  //!  
  30.         sEvent = "PingError"
  31.         break
  32.     default
  33.         break
  34.     } 
  35.     TRACE("handleEvent:-------------%s\n", sEvent.c_str()); 
  36.     return
[cpp] view plaincopy
  1. CEventHandler::CEventHandler():m_nCount(0)  
  2. {  
  3.   
  4. }  
  5.   
  6. CEventHandler::~CEventHandler()  
  7. {  
  8.   
  9. }  
  10.   
  11. void CEventHandler::increaceHeartBeatCount()  
  12. {  
  13.     m_nCount++;  
  14.     return;  
  15. }  
  16.   
  17. void CEventHandler::decreaceHeartBeatCount()  
  18. {  
  19.     if (m_nCount > 0)  
  20.     {  
  21.         m_nCount--;  
  22.     }  
  23.     return;  
  24. }  
  25.   
  26. void CEventHandler::handleEvent(const Event& event)  
  27. {  
  28.     std::string sEvent;  
  29.     switch (event.eventType())  
  30.     {  
  31.     case Event::PingPing:   //! 收到PING消息  
  32.         sEvent = "PingPing";  
  33.         break;  
  34.     case Event::PingPong:   //! 收到返回PONG消息,心跳累计次数减1  
  35.         sEvent = "PingPong";  
  36.         decreaceHeartBeatCount();  
  37.         break;  
  38.     case Event::PingError:  //!   
  39.         sEvent = "PingError";  
  40.         break;  
  41.     default:  
  42.         break;  
  43.     }  
  44.     TRACE("handleEvent:-------------%s\n", sEvent.c_str());  
  45.     return;  
  46. }  

心跳线程:

[cpp] view plaincopy
  1. UINT MessageTest::heartBeatThread(LPVOID lpParam) 
  2.     MessageTest* pThis = (MessageTest*)lpParam; 
  3.     if(NULL == pThis) 
  4.         return -1; 
  5.     CEventHandler* pEventHandler = new CEventHandler(); 
  6.     while (!pThis->m_bDisConnect) 
  7.     { 
  8.         //! 心跳次数大于三次则通知断链重连,本次心跳线程结束 
  9.         if (pEventHandler->getHeartBeatCount() > 3) 
  10.         { 
  11.             break
  12.         } 
  13.          
  14.         pThis->m_client->xmppPing(JID("talk.google.com"), pEventHandler); 
  15.         pEventHandler->increaceHeartBeatCount(); 
  16.         Sleep(10*1000);     //! 发送心跳消息的时间间隔T应由客户端在登录时由服务器返回 
  17.     } 
  18.     delete pEventHandler; 
  19.     TRACE("心跳线程退出\n"); 
  20.     return 0; 
[cpp] view plaincopy
  1. UINT MessageTest::heartBeatThread(LPVOID lpParam)  
  2. {  
  3.     MessageTest* pThis = (MessageTest*)lpParam;  
  4.     if(NULL == pThis)  
  5.         return -1;  
  6.     CEventHandler* pEventHandler = new CEventHandler();  
  7.     while (!pThis->m_bDisConnect)  
  8.     {  
  9.         //! 心跳次数大于三次则通知断链重连,本次心跳线程结束  
  10.         if (pEventHandler->getHeartBeatCount() > 3)  
  11.         {  
  12.             break;  
  13.         }  
  14.           
  15.         pThis->m_client->xmppPing(JID("talk.google.com"), pEventHandler);  
  16.         pEventHandler->increaceHeartBeatCount();  
  17.         Sleep(10*1000);     //! 发送心跳消息的时间间隔T应由客户端在登录时由服务器返回  
  18.     }  
  19.     delete pEventHandler;  
  20.     TRACE("心跳线程退出\n");  
  21.     return 0;  
  22. }  


其它关于心跳的机制,比如心跳时间间隔、断链重连等处理需要根据具体项目来修改以上代码