首页 > 代码库 > 关闭客户端连接的两种情况

关闭客户端连接的两种情况

关于连接状态改变的情况客户端下线的两种方式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.\n"); //BEV_EVENT_EOF        printf("Got an error on the connection: %s channel_id = %d, offline = %d, wait_offline = %d\n",            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之后才能提示下线,关键这种延迟关闭个人感觉也不是太好,让主线程成取写,然后主线程取关闭套接字这样为什么就能保证操作的套接字无效,我也不太清楚

 

关闭客户端连接的两种情况