У меня тот же вопрос, и я нашел причину, почему 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 секунды я получил отключение!