2010-08-22 48 views
3

我正试图在C++/gloox上编写自己的jabber bot。一切都很顺利,但是当互联网连接断开时 - 僵尸认为它仍然连接,并且当连接重新连接时 - 当然机器人不响应任何消息。C++/Gloox:如何检查连接何时关闭?

每次自bot成功连接以来,即使接口关闭并且电缆被拔下,gloox'recv()也会返回ConnNoError。

尝试使用阻塞和非阻塞gloox'连接和recv()和所有没有任何结果。定期检查xmpp服务器在不同线程中的可用性似乎不是一个好主意,所以如何正确检查机器人现在连接还是不连接?

如果不可能只用gloox做 - 请给我一些好的方法,但让它在unix中可用。

回答

3

我有同样的问题,并找到recv总是重演ConnNoError的原因。这是我发现的。当建立连接时,recv的调用一个名为dataAvailable在ConnectionTCPBase.cpp功能可按其返回

((select(m_socket + 1, &fds, 0, 0, timeout == -1 ? 0 : &tv) > 0) && FD_ISSET(m_socket, &fds) != 0) 

谷歌搜索,I found this thread,故称FD_ISSET(m_socket,& FDS)将检测插座readble但不关闭... FD_ISSET(m_socket,& fds)的返回值始终为0,即使网络已关闭。在这种情况下,dataAvailable的返回值为false,因此下面的代码最终会在recv中返回ConnNoError。

if(!dataAvailable(timeout)) 
{ 
    m_recvMutex.unlock(); 
    return ConnNoError; 
} 

我不知道它是一个错误还是什么,似乎不是。

后来我尝试了另一种方式,直接写入套接字,如果套接字关闭,这将导致SIGPIPE,捕获该信号,然后使用清理断开连接。

我终于弄清楚了这个问题的一个优雅的解决方案,使用心跳。

在gloox线程

,调用心跳(),其中m_pClient是一个指针gloox的实例::客户

void CXmpp::heartBeat() 
{ 
    m_pClient->xmppPing(m_pClient->jid(), this); 
    if (++heart) > 3) { 
     m_pClient->disconnect(); 
    } 
} 

xmppPing将自己注册到事件处理程序,当平安回来,它会调用的handleEvent ,并在为handleEvent

void CEventHandler::handleEvent(const Event& event) 
{ 
    std::string sEvent; 
    switch (event.eventType()) 
    { 
     case Event::PingPing: 
      sEvent = "PingPing"; 
      break; 
     case Event::PingPong: 
      sEvent = "PingPong"; 
      //recieve from server, decrease the count of heart 
      --heart; 
      break; 
     case Event::PingError: 
      sEvent = "PingError"; 
      break; 
     default: 
      break; 
    } 
    return; 
} 

连接到服务器,关闭网络,3秒后,我得到了一个断开!