c++仿muduo库实现高并发服务器--connection类

前置声明与枚举定义

cpp 复制代码
class Connection;
// DISCONNECTED 连接关闭状态
// CONNECTING 连接建立成功-待处理状态
// CONNECTED 连接建立完成,各种设置完成,可通信状态
// DISCONNECTING 待关闭状态
typedef enum
{
    DISCONNECTED,
    CONNECTING,
    CONNECTED,
    DISCONNECTING
} ConnStatu;
using PtrConnection = std::shared_ptr<Connection>;

lass Connection; 这是一个类的前置声明,它允许我们在Connection类完整定义之前,使用指向Connection类的指针或引用。比如在定义PtrConnection类型别名时就用到了这个前置声明。

typedef enum {... } ConnStatu; 定义了一个枚举类型ConnStatu,用于清晰地表示连接可能处于的不同状态。DISCONNECTED代表连接关闭状态,CONNECTING表示连接建立成功但还处于待处理状态,CONNECTED意味着连接建立完成,各项设置就绪,可以进行通信,DISCONNECTING则是连接即将关闭的待关闭状态。

using PtrConnection = std::shared_ptr; 创建了一个类型别名PtrConnection,它实际上就是std::shared_ptr,使用这个别名可以方便地管理Connection对象的共享所有权,在后续代码中传递和操作Connection对象时更加简洁。

Connection类定义

cpp 复制代码
class Connection : public std::enable_shared_from_this<Connection>
{
    //...
};

class Connection : public std::enable_shared_from_this 表示Connection类继承自std::enable_shared_from_this。通过这种继承,Connection类可以安全地从自身获取std::shared_ptr管理对象。这在回调函数等场景中非常重要,因为它确保了对象在被共享使用时,其生命周期能够被正确管理,避免了悬空指针等问题。

私有成员函数 - HandleRead

cpp 复制代码
void HandleRead() // 描述符触发可读事件后调用的函数,接收socked数据放到接收缓冲区中,然后调用message_callback
{
    // 1 接收socket数据放到缓冲区
    char buf[65536];
    ssize_t ret = _socket.NoneBlockRecv(buf, 65535);
    if (ret < 0)
    {
        // 出错了,不能直接关闭连接
        return ShutdownInLoop();
    }

    else if (ret == 0) // 这里等于0表示没有读取到数据,并非连接断开,断开是返回-1
    {
        return;
    }
    // 将数据放入输入缓冲区,写入之后顺便将写偏移向后移动
    _in_buffer.WriteAndPush(buf, ret);
    // 2 调用message_callback进行业务处理
    if (_in_buffer.ReadAbleSize() > 0)
    {
        // shared_from_this()从当前对象自身获取自身的shared_ptr管理对象
        return _message_callback(shared_from_this(), &_in_buffer);
    }
}

当描述符触发可读事件时,HandleRead函数会被调用。它的主要职责是从套接字接收数据并放入接收缓冲区,之后调用message_callback来处理业务逻辑。

首先,创建一个大小为65536的字符数组buf,用于接收数据。然后使用_socket.NoneBlockRecv函数从套接字接收数据,该函数尝试接收最多65535字节的数据,并返回实际接收的字节数ret。

如果ret < 0,表示接收数据出错,此时调用ShutdownInLoop函数进行关闭连接的相关处理,但不直接关闭连接,因为可能还有其他后续操作需要处理。

如果ret == 0,说明这次没有读取到数据,但并不意味着连接断开(连接断开通常返回 -1),直接返回,等待下一次事件触发。

若成功读取到数据(ret > 0),将数据写入_in_buffer输入缓冲区,并根据读取的字节数移动写偏移。接着,检查_in_buffer中是否有可读数据,如果有,则通过_message_callback调用业务处理函数,并使用shared_from_this()获取当前对象的std::shared_ptr,将其和_in_buffer的指针传递给回调函数。

私有成员函数 - HandleWrite

cpp 复制代码
void HandleWrite() // 描述符触发可写事件后调用的函数,将发送缓冲区数据进行发送
{
    //_out_buffer中保存的数据就是要发送的数据
    ssize_t ret = _socket.NoneBlockSend(_out_buffer.ReadPosition(), _out_buffer.ReadAbleSize());
    if (ret < 0)
    {
        // 发送错误就该关闭连接,
        if (_in_buffer.ReadAbleSize() > 0)
        {
            _message_callback(shared_from_this(), &_in_buffer);
        }
        return Release(); // 实际的关闭释放操作
    }
    _out_buffer.MoveReadOffset(ret); // 将读偏移向后移动
    if (_out_buffer.ReadAbleSize() == 0)
    {
        _channel.DisableWrite(); // 没有数据发送了,关闭写事件监控
        // 如果当前是连接关闭状态,有数据则发完数据再释放连接,否则直接释放
        if (_statu == DISCONNECTING && _out_buffer.ReadAbleSize() == 0)
        {
            return Release();
        }
    }
    return;
}

当描述符触发可写事件时,HandleWrite函数会被调用,其任务是将发送缓冲区_out_buffer中的数据发送出去。

调用_socket.NoneBlockSend函数尝试发送数据,该函数从_out_buffer的当前读位置开始,发送可读大小的数据,并返回实际发送的字节数ret。

如果ret < 0,表示发送数据出错,此时检查_in_buffer中是否有可读数据,如果有,则调用_message_callback处理这些数据,然后调用Release函数进行连接的关闭和资源释放操作。

如果发送成功(ret >= 0),根据发送的字节数移动_out_buffer的读偏移,以标记已发送的数据。若_out_buffer中没有剩余可读数据(即所有数据都已发送),调用_channel.DisableWrite()关闭写事件监控,避免不必要的事件触发。此外,如果当前连接状态为DISCONNECTING且_out_buffer已无数据,说明所有数据已发送完毕,也调用Release函数释放连接。

私有成员函数 - HandleClose

cpp 复制代码
void HandleClose() // 描述符触发挂断事件
{
    /*一旦连接挂断了,套接字就什么都干不了了,因此有数据待处理就处理一下,完毕关闭连接*/
    if (_in_buffer.ReadAbleSize() > 0)
    {
        _message_callback(shared_from_this(), &_in_buffer);
    }
    return Release();
}

当描述符触发挂断事件时,HandleClose函数被调用。因为连接挂断后,套接字基本无法再进行正常操作,所以先检查_in_buffer中是否有待处理的数据。

如果_in_buffer中有可读数据,调用_message_callback处理这些数据,确保数据在连接关闭前得到适当处理。处理完数据后,调用Release函数释放连接相关的资源,关闭连接。

私有成员函数 - HandleError

cpp 复制代码
void HandleError() // 描述符触发出错事件
{
    return HandleClose();
}

当描述符触发出错事件时,HandleError函数被调用。它直接调用HandleClose函数,这意味着在出错情况下,将按照连接挂断的处理方式来处理,即先处理可能存在的未处理数据,然后释放连接资源。

私有成员函数 - HandleEvent

cpp 复制代码
void HandleEvent() // 描述符触发任意事件:1 刷新连接的活跃度--延迟定时销毁任务 2 调用组件使用者的任意事件回调
{
    if (_enable_inactive_release == true)
    {
        _loop->TimerRefresh(_conn_id);
    }
    if (_event_callback)
    {
        _event_callback(shared_from_this());
    }
}

当描述符触发任意事件时,HandleEvent函数被调用。它有两个主要功能:一是刷新连接的活跃度(如果启用了非活跃销毁功能),二是调用组件使用者设置的任意事件回调函数。

如果_enable_inactive_release为true,表示启用了非活跃连接超时释放功能,此时调用_loop->TimerRefresh(_conn_id)来刷新定时器,延迟连接的定时销毁任务,即延长连接在非活跃状态下的存活时间。

如果_event_callback存在(即组件使用者设置了该回调函数),调用_event_callback(shared_from_this()),将当前连接对象的std::shared_ptr传递给回调函数,以便使用者在回调中进行相应的处理。

私有成员函数 - EstablishedInLoop

cpp 复制代码
void EstablishedInLoop() // 连接获取之后所处的状态下要进行各种设置(启动读监控,调用回调函数)
{
    // 1 修改连接状态
    assert(_statu == CONNECTING); // 当前状态必须是上层的半连接状态
    _statu = CONNECTED; // 当前函数执行完毕,则连接进入已完成连接状态
    // 一旦启动读事件监控有可能会立即触发读事件,如果
    // 2 启动读事件监控
    _channel.EnableRead();

    // 3 调用回调函数
    if (_connected_callback)
        _connected_callback(shared_from_this());
}

EstablishedInLoop函数用于在连接获取后进行一系列必要的设置。

首先,通过assert(_statu == CONNECTING)断言当前连接状态必须为CONNECTING,以确保连接处于正确的阶段。然后将连接状态修改为CONNECTED,表示连接已成功建立并完成各项设置,可以进行通信。

接着,调用_channel.EnableRead()启动读事件监控,使连接能够接收数据。由于启动读事件监控后可能会立即触发读事件,所以这一步需要谨慎处理。

最后,如果_connected_callback回调函数已被设置(即组件使用者提供了该回调),调用_connected_callback(shared_from_this()),通知使用者连接已成功建立,同时将当前连接对象的std::shared_ptr传递给回调函数,以便使用者进行后续操作。

私有成员函数 - ReleaseInLoop

cpp 复制代码
void ReleaseInLoop() // 实际的释放接口
{
    // 1 修改连接状态,将其置为DISCONNECTED
    _statu = DISCONNECTED;
    // 2 移除连接的事件监控
    _channel.Remove();
    // 3 关闭文件描述符
    _socket.Close();
    // 4 如果当前定时器队列中还有定时销毁任务,则取消任务
    if (_loop->HasTimer(_conn_id))
        CancelInactiveReleaseInLoop();
    // 5 调用关闭回调函数,避免先移除服务器管理的连接信息导致Connection被释放,所以要先调用用户的回调函数
    if (_closed_callback)
        _closed_callback(shared_from_this());
    // 移除服务器内部管理的连接信息
    if (_server_closed_callback)
        _closed_callback(shared_from_this());
}

ReleaseInLoop函数是连接释放的实际操作接口。

首先,将连接状态设置为DISCONNECTED,表明连接已关闭。

然后,调用_channel.Remove()移除连接的事件监控,不再监听该连接的任何事件。

接着,调用_socket.Close()关闭与连接关联的文件描述符,释放相关资源。

如果当前定时器队列中存在针对该连接的定时销毁任务(通过_loop->HasTimer(_conn_id)判断),调用CancelInactiveReleaseInLoop()取消该任务,避免在连接已手动关闭的情况下,定时任务再次尝试关闭连接导致错误。

之后,先调用_closed_callback(如果已设置),这是用户定义的连接关闭回调函数,确保用户有机会在连接关闭时进行自定义操作。然后调用_server_closed_callback(如果已设置),用于移除服务器内部管理的连接相关信息。这样的顺序可以避免在移除服务器管理信息后,由于Connection对象被释放而导致回调函数无法正确执行的问题。

私有成员函数 - SendInLoop

cpp 复制代码
// 这个接口并非实际的发送接口,而是将数据放到发送缓冲区,启动可写事件监控
void SendInLoop(Buffer &buf)
{
    if (_statu == DISCONNECTED)
        return;
    _out_buffer.WriteBufferAndPush(buf);
    if (_channel.WriteAble() == false)
    {
        _channel.EnableWrite();
    }
}

SendInLoop函数并非直接进行数据发送,而是将数据放入发送缓冲区,并在必要时启动可写事件监控。

首先检查连接状态,如果连接状态为DISCONNECTED,说明连接已关闭,直接返回,不进行任何操作。

否则,调用_out_buffer.WriteBufferAndPush(buf)将传入的缓冲区buf中的数据写入_out_buffer发送缓冲区。

接着检查_channel的写事件是否已启用(通过_channel.WriteAble()判断),如果未启用,则调用_channel.EnableWrite()启用写事件监控,以便在套接字可写时触发HandleWrite函数,将发送缓冲区中的数据发送出去。

私有成员函数 - ShutdownInLoop

cpp 复制代码
// 这个关闭操作并非实际的连接释放操作,需要判断还有没有数据待处理,待发送
void ShutdownInLoop()
{
    _statu = DISCONNECTING; // 设置连接为半关闭状态
    if (_in_buffer.ReadAbleSize() > 0)
    {
        if (_message_callback)
            _message_callback(shared_from_this(), &_in_buffer);
    }
    // 要么就是写入数据的时候出错关闭,要么是没有待发送数据,直接关闭
    if (_out_buffer.ReadAbleSize() > 0)
    {
        if (_channel.WriteAble() == false)
        {
            _channel.EnableWrite();
        }
    }
    if (_out_buffer.ReadAbleSize() == 0)
    {
        Release();
    }
}

ShutdownInLoop函数用于执行连接关闭的预处理操作,但并非实际释放连接,它需要检查是否还有数据待处理或待发送。

首先将连接状态设置为DISCONNECTING,表示连接进入半关闭状态。

然后检查_in_buffer中是否有可读数据,如果有且_message_callback已设置,调用_message_callback(shared_from_this(), &_in_buffer)处理这些数据,确保数据在连接关闭前得到处理。

接着检查_out_buffer中是否有待发送的数据,如果有且_channel的写事件未启用,调用_channel.EnableWrite()启用写事件监控,以便将数据发送出去。

如果_out_buffer中没有待发送数据(即_out_buffer.ReadAbleSize() == 0),说明所有数据已处理完毕或无需发送,调用Release()函数实际释放连接资源。

私有成员函数 - EnableInactiveReleaseInLoop

cpp 复制代码
// 启动非活跃连接超时释放规则
void EnableInactiveReleaseInLoop(int sec)
{
    // 1 将判断标志 _enable_inactive_release置为true
    _enable_inactive_release = true;
    // 2 如果当时定时销毁任务已经存在,那就刷新延迟
    if (_loop->HasTimer(_conn_id))
    {
        return _loop->TimerRefresh(_conn_id);
    }
    // 3 如果不存在定时销毁任务,则新增
    _loop->TimerAdd(_conn_id, sec, std::bind(&Connection::Release, this));
}

EnableInactiveReleaseInLoop函数用于启动非活跃连接超时释放规则。

首先,将_enable_inactive_release标志设置为true,表示启用非活跃连接超时释放功能。

然后检查定时器队列中是否已经存在针对该连接的定时销毁任务(通过_loop->HasTimer(_conn_id)判断)。如果存在,调用_loop->TimerRefresh(_conn_id)刷新定时器的延迟时间,延长连接在非活跃状态下的存活时间。

如果不存在定时销毁任务,则使用_loop->TimerAdd(_conn_id, sec, std::bind(&Connection::Release, this))添加一个新的定时任务。该任务将在指定的sec秒后触发,触发时会调用Connection::Release函数,从而实现非活跃连接的超时释放。

私有成员函数 - CancelInactiveReleaseInLoop

cpp 复制代码
void CancelInactiveReleaseInLoop()
{
    _enable_inactive_release = false;
    _loop->TimerCancel(_conn_id);
    if (_loop->HasTimer(_conn_id))
    {
        _loop->TimerCancel(_conn_id);
    }
}

CancelInactiveReleaseInLoop函数的主要目的是取消Connection对象的非活跃连接超时释放机制。这意味着原本设置的如果连接在一定时间内未活动就自动释放连接的规则将被取消。

先标记该连接不再需要非活跃超时检查

再向事件循环请求取消与该连接ID关联的定时器,双重检查确保定时器真正被移除

私有成员函数 - UpgradeInLoop

cpp 复制代码
void UpgradeInLoop(const Any &context,
                   const ConnectedCallback &conn,
                   const MessageCallback &msg,
                   const ClosedCallback &closed,
                   const AnyEventCallback &event)
{
    _context = context;
    _connected_callback = conn;
    _message_callback = msg;
    _closed_callback = closed;
    _event_callback = event;
}

UpgradeInLoop函数用于切换协议时重置上下文以及阶段性回调处理函数。

它接受五个参数,分别是上下文context、连接回调conn、消息回调msg、关闭回调closed和任意事件回调event。

函数内部将传入的参数分别赋值给对应的成员变量_context、_connected_callback、_message_callback、_closed_callback和_event_callback。这样在协议切换后,新的上下文和回调函数就会生效,确保连接能按照新的协议规则进行处理。

公共成员函数 - 构造函数

cpp 复制代码
Connection(EventLoop *loop, uint64_t conn_id, int sockfd) : _conn_id(conn_id), _sockfd(sockfd),
                                                          _enable_inactive_release(false), _loop(loop), _statu(CONNECTING), _socket(_sockfd),
                                                          _channel(loop, _sockfd)
{
    _channel.SetCloseCallback(std::bind(&Connection::HandleClose, this));
    _channel.SetEventCallback(std::bind(&Connection::HandleEvent, this));
    _channel.SetReadCallback(std::bind(&Connection::HandleRead, this));
    _channel.SetWriteCallback(std::bind(&Connection::HandleWrite, this));
    _channel.SetErrorCallback(std::bind(&Connection::HandleError, this));
}

构造函数用于初始化Connection对象的成员变量,并设置_channel的各种事件回调函数。

它接受三个参数:EventLoop指针loop,用于关联事件循环;连接唯一 ID conn_id;文件描述符sockfd。

通过成员初始化列表,对_conn_id、_sockfd、_enable_inactive_release(初始化为false)、_loop、_statu(初始化为CONNECTING)、_socket(使用sockfd初始化)和_channel(使用loop和sockfd初始化)进行初始化。

然后使用std::bind将Connection类的各个事件处理函数(HandleClose、HandleEvent、HandleRead、HandleWrite、HandleError)绑定到_channel的相应回调设置函数中。这样,当_channel监测到对应的事件时,就会调用相应的处理函数。

公共成员函数 - 析构函数

cpp 复制代码
~Connection()
{
    DBG_LOG("RELEASE CONNECTION:%p", this);
}

析构函数在Connection对象销毁时被调用。

这里通过DBG_LOG输出日志信息,表明该Connection对象正在被释放,日志中包含对象的地址this,方便调试时追踪对象的销毁情况。

公共成员函数 - Fd

cpp 复制代码
// 获取管理的文件描述符
int Fd()
{
    return _sockfd;
}

Fd函数用于获取与Connection对象关联的文件描述符。

它直接返回成员变量_sockfd的值,外部代码可以通过调用这个函数获取文件描述符,以便在需要时对底层套接字进行操作,如设置套接字选项等。

公共成员函数 - Id

cpp 复制代码
// 获取连接ID
int Id()
{
    return _conn_id;
}

Id函数用于获取Connection对象的唯一标识符。

它直接返回成员变量_conn_id的值,这个 ID 可以用于在服务器中标识和管理不同的连接,例如在连接管理模块中查找特定的连接。

公共成员函数 - Connected

cpp 复制代码
// 是否处于CONNECTED状态
bool Connected()
{
    return (_statu == CONNECTED);
}

Connected函数用于判断Connection对象当前是否处于CONNECTED状态。

它通过比较成员变量_statu与枚举值CONNECTED来确定连接状态,返回true表示连接处于已建立且可通信状态,返回false则表示处于其他状态。

公共成员函数 - SetContext

cpp 复制代码
// 设置上下文--连接建立完成时进行设置调用
void SetContext(const Any &context)
{
    _context = context;
}

SetContext函数用于设置连接的上下文。

在连接建立完成后调用,接受一个Any类型的参数context,并将其赋值给成员变量_context。上下文可以用于存储与连接相关的额外信息,不同的业务逻辑可以根据这个上下文进行不同的处理。

公共成员函数 - GetContext

cpp 复制代码
// 获取上下文,返回指针
Any *GetContext()
{
    return &_context;
}

GetContext函数用于获取连接的上下文指针。

它返回成员变量_context的地址,外部代码可以通过这个指针访问和修改连接的上下文信息。

公共成员函数 - SetConnectedCallback

cpp 复制代码
void SetConnectedCallback(const ConnectedCallback &cb)
{
    _connected_callback = cb;
}

SetConnectedCallback函数用于设置连接建立成功的回调函数。

接受一个ConnectedCallback类型的参数cb,并将其赋值给成员变量_connected_callback。当连接成功建立并进入CONNECTED状态时,会调用这个回调函数通知使用者。

公共成员函数 - SetMessageCallback

cpp 复制代码
void SetMessageCallback(const MessageCallback &cb)
{
    _message_callback = cb;
}

SetMessageCallback函数用于设置消息处理的回调函数。

接受一个MessageCallback类型的参数cb,并将其赋值给成员变量_message_callback。当从套接字接收到数据并放入接收缓冲区后,如果缓冲区有可读数据,就会调用这个回调函数进行业务处理。

公共成员函数 - SetClosedCallback

cpp 复制代码
void SetClosedCallback(const ClosedCallback &cb)
{
    _closed_callback = cb;
}

SetClosedCallback函数用于设置连接关闭的回调函数。

接受一个ClosedCallback类型的参数cb,并将其赋值给成员变量_closed_callback。当连接关闭时,会调用这个回调函数,使用者可以在回调中进行清理资源、记录日志等操作。

公共成员函数 - SetAnyEventCallback

cpp 复制代码
void SetAnyEventCallback(const AnyEventCallback &cb)
{
    _event_callback = cb;
}

SetAnyEventCallback函数用于设置任意事件的回调函数。

接受一个AnyEventCallback类型的参数cb,并将其赋值给成员变量_event_callback。当描述符触发任意事件时,会调用这个回调函数,使用者可以在回调中对各种事件进行统一处理。

公共成员函数 - SetSrvClosedCallback

cpp 复制代码
void SetSrvClosedCallback(const AnyEventCallback &cb)
{
    _server_closed_callback = cb;
}

SetSrvClosedCallback函数用于设置服务器内部管理连接关闭时的回调函数。

接受一个AnyEventCallback类型的参数cb,并将其赋值给成员变量_server_closed_callback。当服务器内部需要移除该连接的管理信息时,会调用这个回调函数,以便在服务器层面进行连接关闭的相关处理。

公共成员函数 - Established

cpp 复制代码
// 连接建立就绪后,进行channel回调设置,启动读监控,调用_connected_callback
void Established()
{
    _loop->RunInLoop(std::bind(&Connection::EstablishedInLoop, this));
}

Established函数用于在连接建立就绪后执行一系列操作。

它通过_loop->RunInLoop将EstablishedInLoop函数放入事件循环中执行。这样做是为了确保这些操作在事件循环的线程上下文中执行,以避免多线程环境下可能出现的竞态条件等问题。EstablishedInLoop函数会进行连接状态修改、启动读事件监控以及调用连接成功回调函数等操作。

公共成员函数 - Send

cpp 复制代码
// 发送数据,将数据发送到缓冲区,启动事件监控																																  
void Send(const char *data, size_t len)
{
    // 外界传入的data,有可能是个临时的空间,我们现在只是把操作压入了任务池,有可能并没有被立即执行
    // 因此有可能执行的时候,data指向的空间已经被释放了
    Buffer buf;
    buf.WriteAndPush(data, len);
    _loop->RunInLoop(std::bind(&Connection::SendInLoop, this, std::move(buf)));
}

Send函数用于发送数据。

由于外界传入的data指针可能指向一个临时空间,而当前只是将发送操作压入任务池,不一定立即执行,为避免执行时data指向的空间已被释放,先创建一个Buffer对象buf,并将data中的数据写入buf。

然后通过_loop->RunInLoop将SendInLoop函数放入事件循环中执行,并将buf以std::move的方式传递,这样可以避免不必要的拷贝,提高效率。SendInLoop函数会将数据放入发送缓冲区,并在必要时启动可写事件监控。

公共成员函数 - Shutdown

cpp 复制代码
// 提供给组件使用者的关闭接口--并不实际关闭,需要判断有没有数据处理																														  
void Shutdown()
{
    _loop->RunInLoop(std::bind(&Connection::ShutdownInLoop, this));
}

Shutdown函数是提供给组件使用者的关闭连接接口。

它通过_loop->RunInLoop将ShutdownInLoop函数放入事件循环中执行。ShutdownInLoop函数会进行连接关闭的预处理操作,如设置连接为半关闭状态,检查并处理接收和发送缓冲区中的数据,在合适的时机调用Release函数实际释放连接资源。这种方式确保了关闭操作在事件循环的线程上下文中进行,避免多线程问题。

公共成员函数 - Release

cpp 复制代码
void Release()
{
    _loop->QueueInLoop(std::bind(&Connection::ReleaseInLoop, this));
}

Release函数用于发起连接释放操作。

它通过_loop->QueueInLoop将ReleaseInLoop函数放入事件循环队列中。ReleaseInLoop函数会实际执行连接释放的操作,包括修改连接状态、移除事件监控、关闭文件描述符、取消定时销毁任务以及调用关闭回调函数等。将其放入事件循环队列可以确保这些操作在合适的时机执行,避免在不合适的线程或时间点进行资源释放导致的错误。

公共成员函数 - EnableInactiveRelease

cpp 复制代码
// 启动非活跃连接销毁,并定义多长时间无通信就是非活跃,添加定时任务																																		  
void EnableInactiveRelease(int sec)
{
    _loop->RunInLoop(std::bind(&Connection::EnableInactiveReleaseInLoop, this, sec));
} 

EnableInactiveRelease函数用于启动非活跃连接销毁机制,并定义非活跃的时间。

它接受一个参数sec,表示非活跃的时间(秒数)。通过_loop->RunInLoop将EnableInactiveReleaseInLoop函数放入事件循环中执行,并将sec传递给EnableInactiveReleaseInLoop函数。EnableInactiveReleaseInLoop函数会设置非活跃销毁标志,检查并刷新或添加定时任务,在指定的非活跃时间后触发连接释放操作。

公共成员函数 - CancelInactiveRelease

cpp 复制代码
void CancelInactiveRelease()
{
    _loop->RunInLoop(std::bind(&Connection::CancelInactiveReleaseInLoop, this));
}

CancelInactiveRelease函数用于取消非活跃连接销毁机制。

通过_loop->RunInLoop将CancelInactiveReleaseInLoop函数放入事件循环中执行。CancelInactiveReleaseInLoop函数会禁用非活跃销毁标志,并取消定时器队列中针对该连接的定时销毁任务,确保连接不会因为非活跃而被释放。

公共成员函数 - Upgrade

cpp 复制代码
// 切换协议--重置上下文以及阶段性回调处理函数--这个接口必须在EventLoop中立即执行
// 防备新的事件触发后,处理时切换任务还没有执行--会导致数据使用原协议处理																													  
void Upgrade(const Any &context,
             const ConnectedCallback &conn,
             const MessageCallback &msg,
             const ClosedCallback &closed,
             const AnyEventCallback &event)
{
    _loop->AssertInLoop();
    _loop->RunInLoop(std::bind(&Connection::UpgradeInLoop, this, context, conn, msg, closed, event));
}

Upgrade函数用于切换协议,重置上下文以及阶段性回调处理函数。

它接受五个参数,分别是上下文context、连接回调conn、消息回调msg、关闭回调closed和任意事件回调event。

首先调用_loop->AssertInLoop()确保当前线程是事件循环线程,防止在错误的线程中调用该函数导致未定义行为。然后通过_loop->RunInLoop将UpgradeInLoop函数放入事件循环中执行,并将上述五个参数传递给UpgradeInLoop函数。这样做是为了确保在切换协议时,新的上下文和回调函数能够及时生效,避免在切换过程中因新事件触发而使用原协议处理数据的问题。

相关推荐
fantasy5_53 小时前
手写一个C++字符串类:从底层理解String的实现
java·jvm·c++
学工科的皮皮志^_^3 小时前
PCIE学习
经验分享·嵌入式硬件·学习·fpga开发·pcie
sanzk3 小时前
S7-PLCSIM Advanced V3.0下载PLC显示红色IP
服务器·网络·tcp/ip
风123456789~3 小时前
【Linux专栏】多层变量的重定向赋值
linux·运维·服务器
江塘3 小时前
机器学习-KNN算法实战及模型评估可视化(C++/Python实现)
开发语言·c++·人工智能·python·算法·机器学习
KL41803 小时前
【QT】窗口
c++·qt
零戚3 小时前
使用cursor/vscode开发服务器远程桌面应用(X11转发)
服务器·ide·vscode
uxiang_blog3 小时前
Linux学习之旅4
linux·运维·学习
white-persist3 小时前
Linux中,vi(vim)编辑器大部分快捷键
linux·运维·服务器·网络·安全·编辑器·vim