muduo网络库:各类功能

news/2024/12/13 16:14:26/

一、

二、各类含义

1、EventLoop类
在Muduo网络库中,EventLoop类是核心组件之一。它的作用是**提供事件循环机制,
**负责管理和调度各种事件(如I/O事件、定时器事件),确保这些事件能够及时被处理,从而实现高效的网络通信。

1.1EventLoop的工作流程大致如下:
创建一个EventLoop对象。
将需要监控的文件描述符和对应的事件类型注册到EventLoop中。
启动事件循环,进入循环体。
在循环体中,使用epoll等系统调用等待事件的发生。
当有事件发生时,调用相应的回调函数来处理这些事件。
重复步骤4和5,直到事件循环停止。

1.2主要属性
looping_:标志事件循环是否正在运行。
quit_:标志是否需要退出事件循环。
poller_:指向Poller对象的指针,Poller封装了具体的I/O多路复用机制(如epoll)。
activeChannels_:存储当前活跃的Channel对象列表。
currentActiveChannel_:当前正在处理的Channel对象。
eventHandling_:标志是否正在处理事件。
callingPendingFunctors_:标志是否正在调用待处理的任务。
mutex_:用于保护任务队列的互斥锁。
pendingFunctors_:待处理任务的队列。
threadId_:运行该EventLoop的线程ID。
timerQueue_:定时器队列,用于管理定时器事件。

1.3主要方法
loop(): 启动事件循环。该方法会进入循环体,不断地等待并处理事件,直到调用quit()方法。
    
quit():  退出事件循环。该方法会设置quit_标志,在安全的时机退出事件循环。
    
runInLoop(Functor cb): 在当前事件循环中执行指定的任务。如果在其他线程中调用该方法,会将任务添加到pendingFunctors_队列中。
    
queueInLoop(Functor cb):将任务添加到待处理任务队列中,在事件循环的下一次迭代时执行。
    
updateChannel(Channel channel): 更新一个Channel,即在Poller中更新该Channel所关注的事件。
removeChannel(Channel channel):移除一个Channel,即在Poller中取消对该Channel的关注。
hasChannel(Channel channel):检查Poller中是否包含指定的Channel。

wakeup():  唤醒事件循环,使其从阻塞状态中退出。通常用于在其他线程中添加任务后通知事件循环执行。

doPendingFunctors():执行待处理任务队列中的所有任务。该方法在事件循环中调用,以确保所有任务都能在事件循环中安全地执行。

handleRead():处理读事件,通常用于处理唤醒事件循环的事件。
handleError():处理错误事件。


1.4事件循环工作流程

启动事件循环:
调用loop()方法,进入事件循环。

等待事件:
调用Poller的poll()方法等待事件发生。

处理事件:
遍历活跃的Channel列表,调用每个Channel的事件处理回调函数。

处理定时器事件:
检查并处理到期的定时器事件。

执行待处理任务:
调用doPendingFunctors()方法,执行在其他线程中添加的任务。

重复循环:
重复上述步骤,直到调用quit()方法退出事件循环。


2、Poller类
Poller类是EventLoop的一个重要组件,负责具体的“I/O多路复用机制”的 “封装”。
Poller类是一个“抽象基类”,它提供了统一的接口,以便不同的具体实现(如使用epoll或poll)
可以继承并实现这些接口(对应两个派生类:PollPoller和EpollPoller)。
具体使用中会根据环境变量的设置选择是使用epoll还是poll方法。
Poller类的主要作用是:管理和分发I/O事件。(实际操作的不是I/O事件,而是Channel类!!)

2.1 主要属性

ownerLoop_:指向所属的EventLoop对象。确保Poller在正确的事件循环线程中被使用。
channels_:保存文件描述符到Channel对象的映射,便于快速查找。

2.2 主要方法

virtual Timestamp poll(int timeoutMs, ChannelList activeChannels) = 0*:   
纯虚函数,“等待事件发生”并将活跃的Channel“填充到”activeChannels列表中。timeoutMs指定等待事件的超时时间。

virtual void updateChannel(Channel channel) = 0*:
纯虚函数,更新指定的Channel。通常涉及将该Channel的文件描述符和事件类型“添加或修改”到多路复用机制中。

virtual void removeChannel(Channel channel) = 0*:  纯虚函数,从多路复用机制中“移除”指定的Channel。

bool hasChannel(Channel channel) const*: 检查Poller中是否包含指定的Channel。通过查找channels_映射实现。

2.3 主要工作流程

创建并初始化Poller:
在创建EventLoop对象时,会根据系统和配置选择具体的Poller实现(如EPollPoller或PollPoller)。

添加、更新和移除Channel:
通过调用updateChannel和removeChannel方法,管理Channel对象及其关注的事件。

等待事件:
在事件循环中,调用poll方法“等待事件发生”,并获取活跃的Channel列表。

分发事件:
将活跃的事件“分发给”相应的Channel对象,Channel对象再调用预先设置的回调函数处理事件。


3、Channel类
在 Muduo 网络库中,Channel 类是一个关键组件,用于表示和管理 文件描述符fd及其相关的 I/O 事件。
它负责将底层的 “I/O 事件” 和 应用层的“回调函数”关联起来,使得事件处理更加抽象和灵活。

3.1 主要属性

loop_: 指向所属的 EventLoop 对象,确保 Channel 所属的事件循环。

fd_:文件描述符,表示这个 Channel 关注的具体文件描述符。

events_:表示当前 Channel 感兴趣的事件,由“位掩码”表示,如 EPOLLIN, EPOLLOUT 等。

revents_:表示实际发生的事件,由 EventLoop 设置。

index_:用于在 Poller 中记录 Channel 的状态(是否在 epoll 或 poll 的关注列表中)。

tied_:表示是否与某个对象(如 TcpConnection)绑定,防止对象在事件处理过程中被销毁。

eventHandling_:标志当前是否正在处理事件。

addedToLoop_:标志当前 Channel 是否已经添加到事件循环中。

readCallback_、writeCallback_、errorCallback_、closeCallback_:一系列的回调函数,用于处理不同类型的事件。


3.2 主要方法

void handleEvent(Timestamp receiveTime);
用途:处理发生的事件,根据 revents_ 的值“调用相应的回调函数”。
参数:receiveTime,表示事件发生的时间戳。
实现逻辑:根据 revents_ 的值,依次调用(错误、关闭、读、写)事件的回调函数。

setReadCallback:设置读事件回调函数;
setWriteCallback:设置写事件回调函数;
setErrorCallback:设置错误事件回调函数;
setCloseCallback:设置关闭事件回调函数。
void setReadCallback(ReadEventCallback cb) { readCallback_ = std::move(cb); }   // 设置读事件回调函数。
void setWriteCallback(EventCallback cb) { writeCallback_ = std::move(cb); }   // 设置写事件回调函数。
void setErrorCallback(EventCallback cb) { errorCallback_ = std::move(cb); }
void setCloseCallback(EventCallback cb) { closeCallback_ = std::move(cb); }
用途:将用户定义的回调函数**Callback_,绑定到相应的事件上。
参数:回调函数对象,使用 std::function(包装器) 封装。

事件“启用/禁用”
void enableReading() { events_ |= kReadEvent; update(); } //事件启用
void enableWriting() { events_ |= kWriteEvent; update(); } //事件启用
void disableReading() { events_ &= ~kReadEvent; update(); } //事件禁用
void disableWriting() { events_ &= ~kWriteEvent; update(); } //事件禁用
void disableAll() { events_ = kNoneEvent; update(); } //事件禁用
用途:启用或禁用 Channel 对特定事件的监听。
实现逻辑:修改 events_ 的值,并调用 update() 方法将修改通知给 Poller。

update()
用途:将 Channel 的状态更新到 Poller 中。
实现逻辑:调用 EventLoop 的 updateChannel 方法,将当前 Channel 的状态同步到 Poller。
void Channel::update() {
    addedToLoop_ = true;
    loop_->updateChannel(this);
}

remove()
用途:从 Poller 中移除当前 Channel。
实现逻辑:调用 EventLoop 的 removeChannel 方法,从 Poller 中删除当前 Channel。
void Channel::remove() {
    addedToLoop_ = false;
    loop_->removeChannel(this);
}

tie()
void tie(const std::shared_ptr<void>& obj);
用途:将 Channel 绑定到一个对象(通常是 TcpConnection),防止在处理事件时该对象被销毁。
参数:一个 std::shared_ptr<void> 对象。
实现逻辑:存储 weak_ptr,在处理事件时检查对象是否有效。
void Channel::tie(const std::shared_ptr<void>& obj) {
    tie_ = obj;
    tied_ = true;
}

其他辅助方法
int fd() const { return fd_; }    // 返回文件描述符。
int events() const { return events_; }   // 返回当前感兴趣的事件。
void set_revents(int revt) { revents_ = revt; } // 设置实际发生的事件。
bool isNoneEvent() const { return events_ == kNoneEvent; }  // 检查是否没有感兴趣的事件。

4、TcpConnection类
在 Muduo 网络库中,TcpConnection 类是一个重要的组件,表示一个“已建立的TCP连接” 和 控制该TCP连接的方法
(连接建立和关闭和销毁),以及这个TCP连接的服务端和客户端的套接字地址信息等。
它封装了 socket 文件描述符,并提供了“处理连接”的各种事件和操作的功能。
TcpConnection 类主要负责(管理连接的生命周期、数据的读写、回调函数的调用)等。

4.1 主要属性

loop_:所属的 EventLoop 对象,表示这个连接归属于哪个事件循环。
name_:连接的名称,通常用来唯一标识一个连接。
state_:连接的状态,如连接建立、连接关闭等。
channel_:对应的 Channel 对象,用于管理 socket 的事件。
socket_:封装的 socket 文件描述符。
inputBuffer_:这是一个Buffer类,是该TCP连接对应的用户接收缓冲区。
outputBuffer_:也是一个Buffer类,不过是用于“暂存”那些暂时发送不出去的待发送数据。 
              因为Tcp发送缓冲区是有大小限制的,假如达到了高水位线,就没办法把发送的数据
              通过send()直接拷贝到Tcp发送缓冲区,而是暂存在这个outputBuffer_中,等TCP发送缓冲区有空间了,
              触发可写事件了,再把outputBuffer_中的数据拷贝到Tcp发送缓冲区中。
connetionCallback_、messageCallback_、writeCompleteCallback_、closeCallback_:
用户会自定义 [连接建立/关闭后的处理函数] 、[收到消息后的处理函数]、[消息发送完后的处理函数]以及Muduo库中定义的[连接关闭后的处理函数]。
这四个函数都会分别注册给这四个成员变量保存。

4.2 主要方法

内部事件处理:handleRead()、handleWrite()、handleClose()、handleError()

私有成员方法,在一个“已经建立好的TCP连接”上主要会发生四类事件:可读事件、可写事件、连接关闭事件、错误事件。
当“事件监听器”监听到一个连接发生了以上的事件,那么就会在EventLoop中“调用”这些事件对应的处理函数,
同时,accept返回已连接套接字所绑定的Channel中注册了这四种回调函数。

void handleRead(Timestamp receiveTime);
void handleWrite();
void handleClose();
void handleError();
// 处理读、写、关闭和错误事件,由 Channel 对象调用。

连接状态的获取和设置
const std::string& name() const { return name_; }
const InetAddress& localAddress() const { return localAddr_; }
const InetAddress& peerAddress() const { return peerAddr_; }
bool connected() const { return state_ == kConnected; }
// 获取连接的名称、本地地址、对端地址和连接状态。

回调函数的设置
void setConnectionCallback(const ConnectionCallback& cb) { connectionCallback_ = cb; }
void setMessageCallback(const MessageCallback& cb) { messageCallback_ = cb; }
void setWriteCompleteCallback(const WriteCompleteCallback& cb) { writeCompleteCallback_ = cb; }
void setCloseCallback(const CloseCallback& cb) { closeCallback_ = cb; }
// 设置(连接、消息、写入完成和关闭)的回调函数。

发送数据
void send(const std::string& message);
void send(Buffer* buf);
// 发送数据,将数据添加到输出缓冲区,并调用 `handleWrite` 方法进行实际发送。

关闭连接
void shutdown();
// 关闭写端,触发连接关闭过程。

强制关闭
void forceClose();
// 强制关闭连接,不等待缓冲区的数据发送完毕。

连接建立和销毁
void connectEstablished();
void connectDestroyed();
// 连接建立时的初始化操作 和 连接销毁时的清理操作。


5、Acceptor类
Acceptor 类在 Muduo 网络库中是一个关键组件,主要负责“接受新的客户端连接”并将其传递给“用户定义的回调函数”。
Acceptor 封装了底层的监听 socket 和 Channel,并提供了对新连接的处理逻辑。

5.1 主要属性

loop_:所属的 EventLoop 对象,表示这个 Acceptor 归属于哪个事件循环。
acceptSocket_:监听 socket,封装了底层的 socket 文件描述符。
acceptChannel_:用于监听事件的 Channel 对象。
listenning_:表示是否处于监听状态。
idleFd_:预留的文件描述符,用于处理文件描述符耗尽的情况。
newConnectionCallback_:新连接到达时的回调函数。

5.2 主要方法

监听
void listen();
用途:启动监听 socket 开始接受新的连接。
实现逻辑:调用 Socket 对象的 listen 方法,并将 acceptChannel 设置为可读状态以处理新的连接。

设置回调函数
void setNewConnectionCallback(const NewConnectionCallback& cb) { newConnectionCallback_ = cb; }
用途:设置新连接到达时的回调函数。

处理新连接
void handleRead();
用途:处理新的连接请求,接受连接并调用用户定义的回调函数。
实现逻辑:调用 Socket 对象的 accept 方法获取新的连接文件描述符,并调用 newConnectionCallback_ 处理新连接。


6、TcpServer类
TcpServer 类在 Muduo 网络库中是一个高层次的网络服务器类,负责管理多个 TCP 连接,
并提供了一些便捷的方法来 设置各种回调函数和启动服务器
它结合了 Acceptor、TcpConnection 等类来处理新的连接和数据传输。

主要属性
loop_:主 EventLoop 对象,用于处理主线程中的事件。
ipPort_:服务器的 IP 和端口。
name_:服务器名称。
acceptor_:Acceptor 对象,负责接受新连接。
threadPool_:用于处理多个 EventLoop 线程的线程池。
connectionCallback_:连接建立或关闭时的回调函数。
messageCallback_:消息到达时的回调函数。
writeCompleteCallback_:数据写入完成时的回调函数。
connections_:管理所有活动连接的容器。


主要方法

void start();  // 启动服务器

// 设置回调函数
void setConnectionCallback(const ConnectionCallback& cb) { connectionCallback_ = cb; }
void setMessageCallback(const MessageCallback& cb) { messageCallback_ = cb; }
void setWriteCompleteCallback(const WriteCompleteCallback& cb) { writeCompleteCallback_ = cb; }

void setThreadNum(int numThreads);  // 设置线程数量

void newConnection(int sockfd, const InetAddress& peerAddr); // 处理新连接

// 移除连接
void removeConnection(const TcpConnectionPtr& conn);
void removeConnectionInLoop(const TcpConnectionPtr& conn);
 


http://www.ppmy.cn/news/1554797.html

相关文章

SSM虾米音乐项目3-后台流派模块的增删改

整体查询到的页面 <div class"widget-header"><i class"icon-list-ol"></i><h3>搜索条件</h3></div><div class"widget-content"><fieldset id"find"><div class"control-gr…

Linux 高级命令大全

Linux 高级命令大全 系统管理 查看所有已加载的服务 systemctl list-units --typeservice 禁用服务的开机自启 systemctl disable service_name 动态启用 IP 转发 sysctl -w net.ipv4.ip_forward1 立即关闭系统 shutdown -h now 重启系统 reboot 查看系统运行时间和负载 …

LightRAG测试BUG

错误一&#xff1a; LightRAG无法回答错误&#xff1a; INFO:lightrag:kw_prompt result:{{"high_level_keywords": ["xxx", "xxx"],"low_level_keywords": ["xxx", "xxx", "xxx"] }} JSON parsing e…

24.DDD与敏捷开发

学习视频来源&#xff1a;DDD独家秘籍视频合集 https://space.bilibili.com/24690212/channel/collectiondetail?sid1940048&ctype0 文章目录 DDD与敏捷开发的关系敏捷宣言DDD与敏捷开发相互助力1. 都强调人与人的协作2. 都强调迭代 DDD与敏捷开发的关系 DDD与敏捷开发不…

访问者模式的理解和实践

在软件开发过程中&#xff0c;设计模式为我们提供了解决常见问题的最佳实践。访问者模式&#xff08;Visitor Pattern&#xff09;是行为设计模式之一&#xff0c;它将数据操作与数据结构分离&#xff0c;使得在不修改数据结构的前提下&#xff0c;能够定义作用于这些元素的新的…

MySQL生产环境备份脚本

全量备份脚本&#xff0c;其中BakDir&#xff0c;ZlbakDir&#xff0c;LogFile需要自己创建 #!/bin/bash export LANGen_US.UTF-8# 指定备份目录 BakDir/root/beifen/data/mysqlbak/data/allbak # 指定增量备份目录 ZlbakDir/root/beifen/data/mysqlbak/data/zlbak # 备份日志…

外卖开发(八)—— SpringTask(定时任务) 和 WebSocket网络协议

外卖开发&#xff08;八&#xff09;—— SpringTask 和 WebSocket 一、利用SpringTask完成定时任务1、cron表达式2、springtask实现 二、使用webSocket实现接单、催单提醒1、代码分析2、催单提醒 一、利用SpringTask完成定时任务 Spring Task是Spring框架提供的任务调度工具&…

Python中的 `string.Template`:用法和使用场景

Python中的 `string.Template`:用法和使用场景 什么是 `string.Template`?`Template` 的基本用法代码解析使用 `safe_substitute`实用场景1. 动态生成消息2. 生成文件内容如何处理复杂场景?总结在Python中,字符串处理是非常常见的任务,其中string.Template提供了一种简单、…