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

关于连接状态改变的情况
客户端下线的两种方式
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之后才能提示下线,关键这种延迟关闭个人感觉也不是太好,让主线程成取写,然后主线程取关闭套接字这样为什么就能保证操作的套接字无效,我也不太清楚

 

TCP是一种面向连接的可靠传输协议,通常在客户端和服务器之间建立一条持久的连接。然而,由于网环境的不稳定性或服务器故障等原因,客户端有时可能会断开与服务器的连接。为保持通信的连续性,客户端需要进行断线重连。 在TCP客户端断线后,重连的步骤如下: 1. 检测断线:客户端首先需要检测与服务器的连接是否断开。一旦检测到断线,客户端将无法通过连接发送或接收数据。 2. 关闭连接客户端需要主动关闭旧的、断开的连接。这样可以释放资源并准备建立新的连接。 3. 重新建立连接客户端会尝试重新建立连接。它会根据服务器地址和端口号,使用TCP握手协议与服务器建立连接。 4. 连接超时处理:如果客户端无法在一定时间内重新建立连接,可能是服务器未启动、网故障或网拥塞等原因。客户端需要进行连接超时处理,可以选择等待一段时间再重新尝试连接。 5. 连接成功后的处理:一旦客户端成功重新建立连接,它可以恢复之前的通信或重新发送之前未发送成功的数据。这样可以保证数据的完整性和连续性。 在进行断线重连时,需要注意以下几点: 1. 定时重连:客户端可以定期尝试重连,避免频繁的连接尝试对服务器造成负载过大的影响。 2. 连接优化:客户端可以在重连时优化连接参数,例如调整超时时间、重试次数等。这样可以提高连接的成功率和重连的效率。 3. 异常处理:客户端在进行断线重连时,需要处理可能出现的异常情况。例如,当网不稳定导致重连失败时,客户端需要进行错误处理,并通知用户或记录日志。 通过断线重连机制,TCP客户端可以在意外断开连接情况下,及时恢复与服务器的连接,确保数据的正常传输。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值