• 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被顺利关闭。

  • 相关阅读:
    Golang进阶实战之IO操作
    动态获取输入框光标在页面中的位置! || 动态添加 style标签 || 获取元素样式 || 获取元素在页面中的位置
    v-select插件
    各种创建数组的方法
    百度UEditor编辑器
    vue-router 各种守卫以及流程梳理
    Snipaste 一款好用的 windows截图工具
    ant-design-vue
    罕见的css样式
    vue图片点击放大预览v-viewer
  • 原文地址:https://www.cnblogs.com/myboat/p/14109942.html
Copyright © 2020-2023  润新知