zoukankan      html  css  js  c++  java
  • ZMQ连接的清理及其context部件的关闭

    一开始使用jeroMQ,由于java会自动回收资源,所以socket对象及context对象的清理比较简单。断开连接和关闭连接不需要考虑连接的状态。所以程序比较简单。

    但在C/C++环境下,zmq连接的处理需要考虑如下情况:

    (1)在zmq_recv()的阻塞状态下,不可能断开连接。

    (2)在连接没有断开和关闭的情况下,context不能关闭(呈阻塞状态)。

    (3)在上面两种情况下,可能会有内存泄漏的问题。

    为了解决以上问题,在C/C++环境下,必须:

    (1)如果没有把握保证zmq_recv()一定能够接收到消息,则必须设置其ZMQ_RCVTIMEO值,使其在接不到消息时可以退出阻塞,以判断是否程序需要退出。

    int recvTime = 500;
    zmq_setsockopt(_socket, ZMQ_RCVTIMEO, &recvTime, sizeof(recvTime));
            ret1 = zmq_recv(_zsocket, sub, 128, 0);
            //接收消息
            if(ret1 == -1)
            {
                int error = zmq_errno();
                cout << "ERROR: messageReceiver socket: wrong message --" << zmq_strerror(error) << endl;
                if(getSimEnd())
                {
                    //closedeliver(); //stop deliver
                    closeCallbackLink(); //stop the callback link
                    cout << "messageReceiver thread closed......2" << endl;
                    return;
                }
            }
    void MessageReceiver::closeCallbackLink()
    {
        //QMutexLocker locker(&_mutex);
        if(_zsocket == nullptr)
            return;
        //setSimEnd();
        //Sleep(500);
        if(_type == tcp)
        {
            char abuf[128];
            memset(abuf, '', 128*sizeof(char));
            sprintf_s(abuf, 128*sizeof(char), "tcp://%s:%d", _rtiHost.c_str(), fport);
            zmq_disconnect(this->_zsocket, abuf);
            zmq_close(_zsocket);
            _zsocket = NULL;
            return;
        }
        if(_type == ipc)
        {
            char abuf[128];
            memset(abuf, '', 128*sizeof(char));
            sprintf_s(abuf, 128*sizeof(char), "ipc://%s", _rtiIpcAddress.c_str());
            zmq_disconnect(this->_zsocket, abuf);
            zmq_close(_zsocket);
            _zsocket = nullptr;
            return;
        }
    }

    (2)在退出阻塞时,要判定是否程序需要退出,如果不退出,则再调用zmq_recv()接收消息,如此循环。

    (3)为了加快断开和关闭连接的速度,设置有限的ZMQ_LINGER值,使连接快速断开。

    int linger = 0;
    zmq_setsockopt(_socket, ZMQ_LINGER, &linger, sizeof(int64_t));

    (4)在(1)中判定需要退出时,应当断开连接和关闭连接,释放socket。

    (5)要想关闭context,必须关闭其上的所有socket,否则关闭context时会阻塞,导致程序无法退出。

    (6)如果连接在线程内,则退出线程和关闭连接尽量同时完成。

    在一个程序中,我在一个context上建立了两个连接,分别被两个线程使用,断开连接并关闭socket后,发现关闭context时总是阻塞,百思不得其解。后来偶然发现,在建立其中一个连接时,使用了zmq_socket_monitor建立了一个监视连接,这个sokcet也是建立在上面的context上的,豁然开朗。将该连接断开并将其socket关闭后,这个context被顺利关闭。

  • 相关阅读:
    认识“委托”
    程序员的修炼之道:从小工到专家(一)
    知识的使用 与 知识的内化
    VB.Net中 Module 的前世今生
    memcached
    C#知识
    Android之垂直显示TextView
    Android开发之各个语言
    Android之hint提示字体大小修改,显示完全
    Android 之计算控件颜色透明度
  • 原文地址:https://www.cnblogs.com/myboat/p/14109942.html
Copyright © 2011-2022 走看看