Ich habe die gleiche Frage und habe den Grund gefunden, warum recv immer ConnNoError zurückgibt. Hier ist, was ich gefunden habe. Wenn die Verbindung aufgebaut ist, ruft recv eine Funktion namens dataAvailable in ConnectionTCPBase.cpp auf, die folgendes zurückgibt
( ( select( m_socket + 1, &fds, 0, 0, timeout == -1 ? 0 : &tv ) > 0 ) && FD_ISSET( m_socket, &fds ) != 0 )
Google durchsuchen, Ich habe diesen Thread gefunden FD_ISSET( m_socket, &fds ) würde erkennen, dass der Socket lesbar, aber nicht geschlossen ist ... Der Rückgabewert von FD_ISSET( m_socket, &fds ) ist immer 0, auch wenn das Netzwerk unterbrochen ist. In diesem Fall ist der Rückgabewert von dataAvailable falsch, so dass der folgende Code schließlich ConnNoError in recv zurückgibt.
if( !dataAvailable( timeout ) )
{
m_recvMutex.unlock();
return ConnNoError;
}
Ich weiß nicht, ob es sich um einen Fehler handelt oder nicht, aber es scheint so.
Später habe ich versucht, einen anderen Weg, schreiben Sie in den Socket direkt, und dies wird ein SIGPIPE verursachen, wenn der Socket geschlossen ist, fangen Sie dieses Signal, dann verwenden Sie cleanup zu trennen.
Ich habe schließlich eine elegante Lösung für dieses Problem gefunden, die Heartbeat verwendet.
im gloox-Thread heartBeat() aufrufen, wobei m_pClient ein Zeiger auf eine Instanz von gloox::Client ist
void CXmpp::heartBeat()
{
m_pClient->xmppPing(m_pClient->jid(), this);
if (++heart) > 3) {
m_pClient->disconnect();
}
}
xmppPing registriert sich bei eventhandler, wenn ping zurückkommt, ruft es handleEvent auf, und 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;
}
mit dem Server verbinden, das Netzwerk ausschalten, 3 Sekunden später wurde die Verbindung unterbrochen!