4 Stimmen

C++ / Gloox: Wie kann man prüfen, ob die Verbindung unterbrochen ist?

Ich versuche, einen eigenen Jabber-Bot in C++/Gloox zu schreiben. Alles geht gut, aber wenn die Internetverbindung unterbrochen ist - Bot denkt, dass es noch verbunden ist, und wenn die Verbindung wieder - natürlich Bot reagiert nicht auf jede Nachricht.

Seitdem der Bot erfolgreich verbunden ist, gibt gloox' recv() jedes Mal ConnNoError zurück, auch wenn die Schnittstelle ausgefallen ist und das Kabel ausgesteckt wurde.

Ich habe versucht, blockierende und nicht-blockierende gloox'-Verbindungen und recv() zu verwenden, aber alles ohne Ergebnis. Regelmäßige Überprüfungen der Verfügbarkeit des xmpp-Servers in verschiedenen Threads scheint nicht wie eine gute Idee, so wie richtig zu überprüfen, ist Bot gerade jetzt verbunden oder nicht?

Wenn es nicht möglich ist, nur mit Gloox zu machen - bitte zeigen Sie mir eine gute Methode, aber lassen Sie es in Unix verfügbar sein.

3voto

buaacss Punkte 757

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!

0voto

v01d Punkte 1407

Sie müssen onDisconnect(ConnectionError e) definieren, um das Trennungsereignis behandeln zu können. Die Adresse für die Dokumentation lautet http://camaya.net/api/gloox-0.9.9.12/classgloox_1_1ConnectionListener.html#a2

CodeJaeger.com

CodeJaeger ist eine Gemeinschaft für Programmierer, die täglich Hilfe erhalten..
Wir haben viele Inhalte, und Sie können auch Ihre eigenen Fragen stellen oder die Fragen anderer Leute lösen.

Powered by:

X