zoukankan      html  css  js  c++  java
  • 关闭客户端连接的两种情况

    关于连接状态改变的情况
    客户端下线的两种方式
    1.客户端主动下线
    子线程会收到socket状态改变的消息
    /* 连接状态改变 */
    static void conn_eventcb(struct bufferevent *bev, short events, void *user_data)
    {
        auto c2 = (Channel2*)user_data;
        auto c = c2->channel;
        if(c->m_is_disconnected)
        {
            int a = 0;
            return ;
        }
        static int offline = 0;
        if((events & BEV_EVENT_EOF) || (events & BEV_EVENT_ERROR)) 
        {
            { //如果已经下线,即不用做下线处理
                std::lock_guard<std::mutex> lock(c2->ser->m_lts_mtx);
                if(!c2->ser->m_allChannels[c->m_id])
                    return;
            }
            //printf("Connection closed.
    "); //BEV_EVENT_EOF
            printf("Got an error on the connection: %s channel_id = %d, offline = %d, wait_offline = %d
    ",
                strerror(errno), c->m_id, ++offline, c2->ser->m_offline_que.size());/*XXX win32*/
            {
                c->m_is_disconnected = true;
                c->m_event->on_stat_change(c->m_id, link_stat::link_disconnected);
            }
            {
                auto ser = c2->ser;
                LibEvtServer::OffChannel2 offc2 = { GetTickCount(), bev->ev_read.ev_fd, c2};
    
                {//防止libevent thread 和 主线程(send_data)同时访问m_offline_que。
                    std::lock_guard<std::mutex> lock(ser->m_offline_mtx);
                    ser->m_offline_que.push(offc2);
    #ifdef MUL_LIBEVENT_THREAD
                }
                {//防止多个libevent thread 线程同时访问下面公共变量
                    std::lock_guard<std::mutex> lock(ser->m_lts_mtx);
    #endif
                    ser->m_allChannels[c->m_id] = NULL;
                    ser->m_ids->freeId(c->m_id);//[L]将id归还。
                }
                //int read_fd = bev->ev_read.ev_fd;
                //int write_fd = bev->ev_write.ev_fd;
            }
        
        }
        /* None of the other events can happen here, since we haven't enabled
         * timeouts */
    }
    
    2.踢下线
    bool LibEvtServer::close_channel(int channel_id)
    {
        auto c2 = m_allChannels[channel_id];
        if(!c2->channel || c2->channel->m_is_disconnected)
            return false;
    
        auto c = c2->channel;
        LibEvtServer::OffChannel2 offc2 = { GetTickCount(), c->m_bev->ev_read.ev_fd, c2};
        {
            std::lock_guard<std::mutex> lock(m_offline_mtx);
            m_offline_que.push(offc2);//他也是将其push到这个下线队列中
    #ifdef MUL_LIBEVENT_THREAD
        }
        {//防止多个libevent thread 线程同时访问下面公共变量
            std::lock_guard<std::mutex> lock(m_lts_mtx);
    #endif
            m_allChannels[c->m_id] = NULL;
            m_ids->freeId(c->m_id);//[L]将id归还。
        }
        return true;
    }
    
    在主线程中是什么时候关闭套接字的呢
    在包发送超过100个的时候执行一次下线
    bool LibEvtServer::free_one_link()
    {
        /**
         *①让主线程来决定连接,为了保证bufferevent_write的第一个参数绝对有效;
         *②一次处理一个,保证实时性。
         */
        if(m_offline_que.size())
        {
            OffChannel2* offc2 = NULL;
            {
                std::lock_guard<std::mutex> lock(m_offline_mtx);
                offc2 = &(m_offline_que.front());//注意需要用成员的引用或地址
            }
            if(offc2->c2)
            {
                delete offc2->c2->channel;//bufferevent_free(...)
                delete offc2->c2;
                offc2->c2 = nullptr;
            }
            if((GetTickCount() - offc2->offtime) > 60*1000)//延时60秒关闭套接字,保证工作线程调完套接字操作
            {
                evutil_closesocket(offc2->sockfd);    //跨平台关闭套接字函数:Linux - close(fd); Windows - closesocket(fd)
                std::lock_guard<std::mutex> lock(m_offline_mtx);
                m_offline_que.pop();
            }
        }
    
        return false;
    }
    注意这个写直接是主线程在写,读是在线程,释放连接也是在主线程,在线程释放连接时会延迟60s,防止子线程对socket进行读操作,
    这就造成了踢下线客户端不能及时收到通知,得1min之后才能提示下线,关键这种延迟关闭个人感觉也不是太好,让主线程成取写,然后主线程取关闭套接字这样为什么就能保证操作的套接字无效,我也不太清楚
  • 相关阅读:
    SQLServer 2008数据库查看死锁、堵塞的SQL语句
    Jmeter(三)简单的HTTP请求(非录制)
    watir中不能打开页面中的URL超链接解决办法
    我要搬博客到这里来,请协助
    Jmeter(一)精简测试脚本
    性能测试机中存在大量的TIME_WAIT状态的连接,影响并发压力的发起
    ruby+watir随机而不重复获取Menu菜单的元素
    Eclipse中安装Ruby的插件org.rubypeople.rdt
    TCP连接各状态数量、以及TCP各状态变迁流程
    ruby+watirwatir3.0上实现快照/截图
  • 原文地址:https://www.cnblogs.com/zzyoucan/p/4101579.html
Copyright © 2011-2022 走看看