C++ / Gloox:如何检查连接何时断开?

发布于 2024-09-15 20:46:23 字数 332 浏览 4 评论 0原文

我正在尝试在 c++/gloox 上编写自己的 jabber 机器人。一切都很顺利,但是当互联网连接断开时 - 机器人认为它仍然处于连接状态,而当连接再次接通时 - 当然机器人不会响应任何消息。

自从机器人成功连接以来,每次 gloox 的 receive() 都会返回 ConnNoError,即使接口已关闭并且电缆已拔出。

尝试使用阻塞和非阻塞 gloox 的连接和 recv() ,但没有任何结果。定期检查不同线程中 xmpp 服务器的可用性似乎不是一个好主意,那么如何正确检查机器人现在是否已连接?

如果仅使用 gloox 无法做到这一点 - 请指出我一些好的方法,但让它在 unix 中可用。

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 bot 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.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

梦幻的心爱 2024-09-22 20:46:23

我也有同样的问题,找到了recv总是rerun ConnNoError的原因。这是我发现的。建立连接后,recv 会调用 ConnectionTCPBase.cpp 中名为 dataAvailable 的函数,该函数返回

( ( 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,所以下面的代码最终在recv中返回ConnNoError。

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

不知道是bug还是什么,好像不是。

后来我尝试了另一种方法,直接写入套接字,如果套接字关闭,这将导致 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会将自身注册到eventhandler,当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秒后,我就断线了!

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!

瑕疵 2024-09-22 20:46:23

您必须定义 onDisconnect(ConnectionError e) 才能处理断开连接事件。文档地址为 http://camaya.net/api/gloox- 0.9.9.12/classgloox_1_1ConnectionListener.html#a2

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

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文