C ++ / Gloox: как проверить, когда соединение не работает? - PullRequest
3 голосов
/ 23 августа 2010

Я пытаюсь написать свой собственный джаббер-бот на c ++ / gloox. Все идет хорошо, но когда интернет-соединение не работает - бот думает, что оно все еще подключено, а когда соединение снова установлено - конечно, бот не отвечает ни на одно сообщение.

Каждый раз, когда бот успешно подключается, gloox 'recv () возвращает ConnNoError, даже если интерфейс не работает и кабель отключен.

Пробовал использовать блокирующие и неблокирующие соединения gloox 'и recv () и все было безрезультатно. Периодические проверки доступности сервера xmpp в другом потоке не кажутся хорошей идеей, так как правильно проверить, подключен ли бот прямо сейчас или нет?

Если это невозможно сделать только с глоксом, укажите мне какой-нибудь хороший метод, но пусть он будет доступен в unix.

Ответы [ 2 ]

3 голосов
/ 04 октября 2012

У меня тот же вопрос, и я нашел причину, почему recv всегда запускает ConnNoError. Вот что я нашел. Когда соединение установлено, recv вызывает функцию с именем dataAvailable In ConnectionTCPBase.cpp, которая возвращает

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

поиск в Google, Я нашел этот поток , он сказал, что FD_ISSET (m_socket, & fds) обнаружит, что сокет доступен для чтения, но не закрыт ... Возвращаемое значение FD_ISSET (m_socket, & fds) всегда равно 0 даже сеть не работает. В таком случае возвращаемое значение dataAvailable равно false, поэтому приведенный ниже код, наконец, возвращает ConnNoError в recv.

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

Не знаю, баг это или нет, похоже нет.

Позже я попробовал другой способ, напрямую написать в сокет, и это вызовет SIGPIPE, если сокет закрыт, перехватите этот сигнал, а затем используйте cleanup для отключения.

Наконец-то я нашел изящное решение этой проблемы, используя сердцебиение.

в потоке gloox вызовите heartBeat (), где m_pClient - указатель на экземпляр gloox :: Client

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

xmppPing зарегистрируется в обработчике событий, когда 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 секунды я получил отключение!

0 голосов
/ 12 октября 2011

Вы должны определить onDisconnect (ConnectionError e), чтобы иметь возможность обрабатывать событие отключения. Адрес к документации: http://camaya.net/api/gloox-0.9.9.12/classgloox_1_1ConnectionListener.html#a2

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...