C++ / Gloox: how to check when connection is down?
I'm trying to write own jabber bot on c++/gloox. Everything goes fine, but when internet connection is down - bot thinks that it's still connected, and when connection is up again - of course bot doesn't respond to any message.
Each time since b开发者_开发技巧ot is successfully connected gloox' recv() returns ConnNoError, even if interface is down and cable unplugged.
Tried use blocking and non-blocking gloox' connection and recv() and all was without any result. Periodic checks of availability of xmpp server in different thread is not seems like a good idea, so how to properly check is bot connected right now or no?
If it's not possible to do with gloox only - please point me on some good method, but let it be availible in unix.
I have the same question, and found the reason why recv always retrun ConnNoError. Here is what I found. When the connection is established, the recv calls a funciton named dataAvailable In ConnectionTCPBase.cpp which return
( ( select( m_socket + 1, &fds, 0, 0, timeout == -1 ? 0 : &tv ) > 0 ) && FD_ISSET( m_socket, &fds ) != 0 )
searching google, I found this thread, it said FD_ISSET( m_socket, &fds ) would detect the socket is readble but not is closed ... Return value of FD_ISSET( m_socket, &fds ) is always 0, even the network is down. In such case, the return value of dataAvailable is false, so the code below finally returns ConnNoError in recv.
if( !dataAvailable( timeout ) )
{
m_recvMutex.unlock();
return ConnNoError;
}
I don't know whether it is a bug or what, seems not.
Later I tried another way, write to the socket directly, and this will cause a SIGPIPE if the socket is closed, catch that signal, then use cleanup to disconnect.
I finally figure out a graceful solution to this problem, using heartbeat.
in the gloox thread, call heartBeat(), where m_pClient is an pointer to a instance of gloox::Client
void CXmpp::heartBeat()
{
m_pClient->xmppPing(m_pClient->jid(), this);
if (++heart) > 3) {
m_pClient->disconnect();
}
}
xmppPing will register itself to eventhandler, when ping comes back, it will call handleEvent, and in 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;
}
connect to the server, turn off the network, 3 seconds later, I got a disconnect!
You have to define the onDisconnect(ConnectionError e) to be able to handle the disconnect event. The address to documentation is http://camaya.net/api/gloox-0.9.9.12/classgloox_1_1ConnectionListener.html#a2
精彩评论