我正在尝试在c ++ / gloox上编写自己的jabber机器人。 一切都很顺利,但是当互联网连接断开时 – 僵尸认为它仍然连接,当连接重新启动 – 当然机器人不响应任何消息。
每次自bot成功连接gloox'recv()将返回ConnNoError,即使接口已closures且电缆已拔出。
尝试使用阻塞和非阻塞gloox'连接和recv()和所有没有任何结果。 在不同的线程定期检查xmpp服务器的可用性似乎不是一个好主意,所以如何正确检查机器人现在连接或不连接?
如果只能用gloox进行处理,请给我一些好的方法,但是可以在unix中使用它。
我有同样的问题,并找到recv总是重演ConnNoError的原因。 这是我发现的。 当连接建立时,recv调用一个名为dataAvailable的函数,在ConnectionTCPBase.cpp中返回
( ( select( m_socket + 1, &fds, 0, 0, timeout == -1 ? 0 : &tv ) > 0 ) && FD_ISSET( m_socket, &fds ) != 0 )
搜索谷歌, 我发现这个线程 ,它表示FD_ISSET(m_socket,&fds)将检测到套接字是可读的,但没有关闭… FD_ISSET(m_socket,&fds)的返回值始终为0,即使网络已关闭。 在这种情况下,dataAvailable的返回值是false,所以下面的代码最终在recv中返回ConnNoError。
if( !dataAvailable( timeout ) ) { m_recvMutex.unlock(); return ConnNoError; }
我不知道这是一个错误还是什么,似乎不是。
后来我尝试了另一种方式,直接写入套接字,这将导致SIGPIPE,如果套接字关闭,捕获该信号,然后使用清理断开连接。
我终于弄清楚了这个问题的一个优美的解决方案,使用心跳。
在gloox线程中,调用heartBeat(),其中m_pClient是指向gloox :: Client实例的指针
void CXmpp::heartBeat() { m_pClient->xmppPing(m_pClient->jid(), this); if (++heart) > 3) { m_pClient->disconnect(); } }
xmppPing将自己注册到eventhandler,当ping回来,它会调用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秒钟后,我断开了连接!
您必须定义onDisconnect(ConnectionError e)才能处理断开事件。 文档的地址是http://camaya.net/api/gloox-0.9.9.12/classgloox_1_1Connectionlistner.html#a2