当前位置: 首页 > wzjs >正文

网站建设开发公司cps游戏推广平台

网站建设开发公司,cps游戏推广平台,小男孩与大人做的网站,邯郸制作网站一、引言 在网络编程中,事件驱动是一种常见的编程模型。Muduo 网络库作为一个高效的 C 网络库,采用了事件驱动的设计思想。其中,Channel类在整个架构中扮演着非常重要的角色,它负责封装文件描述符(fd)和与…

一、引言

在网络编程中,事件驱动是一种常见的编程模型。Muduo 网络库作为一个高效的 C++ 网络库,采用了事件驱动的设计思想。其中,Channel类在整个架构中扮演着非常重要的角色,它负责封装文件描述符(fd)和与之关联的事件,并处理这些事件的回调。本文将详细介绍 Muduo 网络库中的Channel类。

二、Channel类的作用

Channel类是 Muduo 网络库中一个核心的组件,它的主要作用是将一个文件描述符(如 socket fd)和该文件描述符上感兴趣的事件(如读事件、写事件等)关联起来,在事件发生时上层通过set_revents方法设置发生事件类型并调用相应的回调函数。简单来说,Channel类就像是一个桥梁,连接了底层的 I/O 多路复用机制(如epollpoll等)和上层的业务逻辑。(在后续完成poller和eventloop后会分析三者之间调用逻辑)

三、Channel类的代码结构与关键成员

3.1 头文件包含与前置声明

#pragma once#include "NonCopyable.h"
#include "Timestamp.h"#include <functional>
#include <memory>class EventLoop;

这里包含了必要的头文件,如NonCopyable.hTimestamp.h,并使用了std::functionstd::memory。同时,对EventLoop类进行了前置声明,由于在Channel的头文件中只使用了EventLoop的指针,不访问其具体实现所以不需要引用其头文件,避免了头文件的循环包含。

3.2 类的定义与继承

class Channel: NonCopyable
{
public:// ...
private:// ...
};

Channel类继承自NonCopyable,这意味着该类的对象不能被复制,防止了不必要的对象复制操作,提高了性能。

NonCopyable定义:

class NonCopyable
{
protected:NonCopyable(){}~NonCopyable(){}NonCopyable(const NonCopyable&) = delete;NonCopyable& operator=(const NonCopyable&) = delete;
};

通过删除类的拷贝构造,赋值运算符实现类及其派生类无法被复制

3.3 回调函数类型定义

using EventCallback = std::function<void()>;
using ReadEventCallback = std::function<void(Timestamp)>;

这里定义了两种回调函数类型:EventCallbackReadEventCallbackEventCallback是一个无参数的回调函数,而ReadEventCallback是一个带有Timestamp参数的回调函数,用于处理读事件。

3.4 构造函数与析构函数

Channel(EventLoop *loop, int fd);
~Channel() = default;

构造函数接受一个EventLoop指针(channel所属的loop)和一个文件描述符(channel管理的文件描述符)作为参数,用于初始化Channel对象。析构函数使用了default关键字,采用默认的析构行为(因为类的成员中只有loop_是裸指针,但其生命周期显然长于channel,析构时没有成员需要手动清理)。

Channel::Channel(EventLoop *loop, int fd): loop_(loop), fd_(fd), events_(0), revents_(0), index_(-1), tied_(false)
{
}

3.5 事件处理函数

void handleEvent(Timestamp receiveTime);

该函数用于处理文件描述符上发生的事件,根据revents_的值调用相应的回调函数。

void Channel::handleEvent(Timestamp receiveTime)
{if (tied_){std::shared_ptr<void> guard = tie_.lock();if (guard){handleEventWithGuard(receiveTime);}// 如果提升失败了 就不做任何处理 说明Channel的TcpConnection对象已经不存在了}else{handleEventWithGuard(receiveTime);}
}

handleEvent 方法用于处理文件描述符上发生的事件。如果 tied_ 为 true,则先尝试提升 tie_ 所指向的 std::shared_ptr 对象,如果提升成功则调用 handleEventWithGuard 方法处理事件;如果提升失败,则不做任何处理。如果 tied_ 为 false,则直接调用 handleEventWithGuard 方法处理事件。

void Channel::handleEventWithGuard(Timestamp receiveTime)
{LOG_INFO << "channel handleEvent revents: " << revents_;// 关闭if ((revents_ & EPOLLHUP) && !(revents_ & EPOLLIN)){if (closeCallback_){closeCallback_();}}// 错误if (revents_ & EPOLLERR){if (errorCallback_){errorCallback_();}}// 读if (revents_ & (EPOLLIN | EPOLLPRI)){if (readCallback_){readCallback_(receiveTime);}}// 写if (revents_ & EPOLLOUT){if (writeCallback_){writeCallback_();}}
}

handleEventWithGuard 方法根据内核返回的实际发生的事件(revents_)调用相应的回调函数。

  • 关闭事件:当 revents_ 包含 EPOLLHUP 且不包含 EPOLLIN 时,表示文件描述符被关闭,调用 closeCallback_ 回调函数。
  • 错误事件:当 revents_ 包含 EPOLLERR 时,表示文件描述符发生错误,调用 errorCallback_ 回调函数。
  • 读事件:当 revents_ 包含 EPOLLIN 或 EPOLLPRI 时,表示文件描述符有数据可读,调用 readCallback_ 回调函数。
  • 写事件:当 revents_ 包含 EPOLLOUT 时,表示文件描述符可以写数据,调用 writeCallback_ 回调函数。

3.6 回调函数设置

void setReadCallback(ReadEventCallback cb) { readCallback_ = std::move(cb); }
void setWriteCallback(EventCallback cb) { writeCallback_ = std::move(cb); }
void setCloseCallback(EventCallback cb) { closeCallback_ = std::move(cb); }
void setErrorCallback(EventCallback cb) { errorCallback_ = std::move(cb); }

这些函数用于设置不同类型事件的回调函数,分别是读事件、写事件、关闭事件和错误事件的回调函数。(由于设置回调的调用并不频繁,这里没有写成接收左右值引用传递的方法,但写了更好)

3.7 事件状态操作

void enableReading() { events_ |= kReadEvent; update(); }
void disableReading() { events_ &= ~kReadEvent; update(); }
void enableWriting() { events_ |= kWriteEvent; update(); }
void disableWriting() { events_ &= ~kWriteEvent; update(); }
void disableAll() { events_ = kNoneEvent; update(); }

这些函数用于启用或禁用文件描述符上的读事件、写事件,以及禁用所有事件。每次修改事件状态后,都会调用update()函数更新事件。

void Channel::update()
{// 通过channel所属的eventloop,调用poller的相应方法,注册fd的events事件loop_->updateChannel(this);
}

更新事件需要epoll_ctl函数执行,但其具体实现被封装到poller类中,那么需要通过channel和poller的管理者eventloop作为桥梁,所以update 方法借助其所属的 EventLoop 来调用 Poller 的相应方法来注册或更新该文件描述符上关注的事件。

3.8 其他成员函数

void tie(const std::shared_ptr<void> &);
int fd() const { return fd_; }
int events() const { return events_; }
void set_revents(int revt) { revents_ = revt; }
bool isNoneEvent() const { return events_ == kNoneEvent; }
bool isWriting() const { return events_ & kWriteEvent; }
bool isReading() const { return events_ & kReadEvent; }
int index() { return index_; }
void set_index(int idx) { index_ = idx; }
EventLoop *ownerLoop() { return loop_; }
void remove();

这些函数提供了获取文件描述符、事件状态、索引等信息的接口,以及绑定对象、移除Channel等操作。

void Channel::remove()
{loop_->removeChannel(this);
}

remove 方法用于从 EventLoop 中移除该 ChannelEventLoop 会调用 Poller 的相应方法来移除该文件描述符上的事件注册 

3.9 私有成员变量

private:void update();void handleEventWithGuard(Timestamp receiveTime);//这两个私有方法实现见上文static const int kNoneEvent;static const int kReadEvent;static const int kWriteEvent;EventLoop *loop_; // 事件循环const int fd_;    // fd,Poller监听的对象int events_;      // 注册fd感兴趣的事件int revents_;     // Poller返回的具体发生的事件int index_;std::weak_ptr<void> tie_;bool tied_;ReadEventCallback readCallback_;EventCallback writeCallback_;EventCallback closeCallback_;EventCallback errorCallback_;/*
const int Channel::kNoneEvent = 0; //空事件
const int Channel::kReadEvent = EPOLLIN | EPOLLPRI; //读事件
const int Channel::kWriteEvent = EPOLLOUT; //写事件
*/
  • loop_:指向所属的EventLoop对象,用于事件循环。
  • fd_:文件描述符,是Poller监听的对象。
  • events_:注册的文件描述符感兴趣的事件。
  • revents_Poller返回的具体发生的事件。
  • index_ChannelPoller中的索引。
  • tie_tied_:用于绑定对象,防止在处理事件时对象被提前销毁。
  • readCallback_writeCallback_closeCallback_errorCallback_:分别是读事件、写事件、关闭事件和错误事件的回调函数。

四、总结

4.1 类内参数总结

  • loop_:指向所属的EventLoop对象,用于事件循环,确保Channel对象能在正确的事件循环中工作。
  • fd_:文件描述符,是Poller监听的对象,代表了一个具体的 I/O 资源。
  • events_:注册的文件描述符感兴趣的事件,通过enableReading()enableWriting()等函数进行设置。
  • revents_Poller返回的具体发生的事件,由Poller在检测到事件后设置。
  • index_ChannelPoller中的索引,用于Poller管理Channel对象。
  • tie_tied_:用于绑定对象,防止在处理事件时对象被提前销毁,提高了程序的安全性。

4.2 回调函数总结

  • readCallback_:读事件回调函数,由上层传递,用于处理文件描述符上的读事件。
  • writeCallback_:写事件回调函数,由上层传递,用于处理文件描述符上的写事件。
  • closeCallback_:关闭事件回调函数,由上层传递,用于处理文件描述符关闭的情况。
  • errorCallback_:错误事件回调函数,由上层传递,用于处理文件描述符上发生的错误事件。

通过Channel类,Muduo 网络库将底层的 I/O 多路复用机制和上层的业务逻辑进行了有效的分离,提高了代码的可维护性和可扩展性。同时,通过回调函数的方式,使得上层业务逻辑可以方便地处理不同类型的事件,增强了代码的灵活性。

附录:

#pragma once#include "NonCopyable.h"
#include "Timestamp.h"#include <functional>
#include <memory>class EventLoop;class Channel: NonCopyable
{
public:using EventCallback = std::function<void()>;using ReadEventCallback = std::function<void(Timestamp)>;Channel(EventLoop *loop, int fd);~Channel() = default;void handleEvent(Timestamp receiveTime);void setReadCallback(ReadEventCallback cb) { readCallback_ = std::move(cb); }void setWriteCallback(EventCallback cb) { writeCallback_ = std::move(cb); }void setCloseCallback(EventCallback cb) { closeCallback_ = std::move(cb); }void setErrorCallback(EventCallback cb) { errorCallback_ = std::move(cb); }void tie(const std::shared_ptr<void> &);int fd() const { return fd_; }int events() const { return events_; }void set_revents(int revt) { revents_ = revt; }void enableReading() { events_ |= kReadEvent; update(); }void disableReading() { events_ &= ~kReadEvent; update(); }void enableWriting() { events_ |= kWriteEvent; update(); }void disableWriting() { events_ &= ~kWriteEvent; update(); }void disableAll() { events_ = kNoneEvent; update(); }bool isNoneEvent() const { return events_ == kNoneEvent; }bool isWriting() const { return events_ & kWriteEvent; }bool isReading() const { return events_ & kReadEvent; }int index() { return index_; }void set_index(int idx) { index_ = idx; }EventLoop *ownerLoop() { return loop_; }void remove();private:void update();void handleEventWithGuard(Timestamp receiveTime);static const int kNoneEvent;static const int kReadEvent;static const int kWriteEvent;EventLoop *loop_; // 事件循环const int fd_;    // fd,Poller监听的对象int events_;      // 注册fd感兴趣的事件int revents_;     // Poller返回的具体发生的事件int index_;std::weak_ptr<void> tie_;bool tied_;ReadEventCallback readCallback_;EventCallback writeCallback_;EventCallback closeCallback_;EventCallback errorCallback_;
};
#include "LogStream.h"
#include "Channel.h"
#include "EventLoop.h"#include <sys/epoll.h>const int Channel::kNoneEvent = 0; //空事件
const int Channel::kReadEvent = EPOLLIN | EPOLLPRI; //读事件
const int Channel::kWriteEvent = EPOLLOUT; //写事件Channel::Channel(EventLoop *loop, int fd): loop_(loop), fd_(fd), events_(0), revents_(0), index_(-1), tied_(false)
{
}void Channel::tie(const std::shared_ptr<void> &obj)
{tie_ = obj;tied_ = true;
}void Channel::update()
{// 通过channel所属的eventloop,调用poller的相应方法,注册fd的events事件loop_->updateChannel(this);
}void Channel::remove()
{loop_->removeChannel(this);
}void Channel::handleEvent(Timestamp receiveTime)
{if (tied_){std::shared_ptr<void> guard = tie_.lock();if (guard){handleEventWithGuard(receiveTime);}// 如果提升失败了 就不做任何处理 说明Channel的TcpConnection对象已经不存在了}else{handleEventWithGuard(receiveTime);}
}void Channel::handleEventWithGuard(Timestamp receiveTime)
{LOG_INFO << "channel handleEvent revents: " << revents_;// 关闭if ((revents_ & EPOLLHUP) && !(revents_ & EPOLLIN)){if (closeCallback_){closeCallback_();}}// 错误if (revents_ & EPOLLERR){if (errorCallback_){errorCallback_();}}// 读if (revents_ & (EPOLLIN | EPOLLPRI)){if (readCallback_){readCallback_(receiveTime);}}// 写if (revents_ & EPOLLOUT){if (writeCallback_){writeCallback_();}}
}
http://www.dtcms.com/wzjs/253599.html

相关文章:

  • 网站标题怎么改深圳百度seo代理
  • 色弱可以做网站开发吗百度推广合作
  • ipv6做网站台州网站优化公司
  • 建设网站的企业邮箱网站建设服务seo课程培训班
  • 近期做网站需要什么软件品牌宣传推广策划方案
  • 网页制作详细步骤win7优化工具哪个好用
  • 北京网站设计公司招聘信息长沙网红打卡景点排行榜
  • 环球资源网商务网站建设目的如何查一个关键词的搜索量
  • 洛阳做网站公司宣传渠道有哪些
  • wordpress文章前台看不到seo整体优化
  • 太原网站制作维护关键词排名什么意思
  • 做服务器的网站都有哪些功能企业营销策略有哪些
  • 企业如何做网站推广指数基金定投技巧
  • 做网站ie10缓存优化营商环境个人心得
  • 做网站需要套模板下载百度安装
  • 3有免费建网站seo网站优化公司
  • 招聘网站分析报告怎么做国际军事新闻
  • 在360网站上怎么做推广福州关键词搜索排名
  • 美国站点网站怎么做市场推广方案怎么写
  • 如何做网站ab测试香港seo公司
  • 什么企业适合做网站品牌营销理论
  • 宝安网站建设公司百度推广联盟
  • 做网站用别人图片文章会侵权吗西安搜建站科技网站
  • 街道人大网站建设搜索引擎优化原理
  • 制作网站需要怎么做优化近义词
  • 做网站珠海原创文章代写平台
  • 广告设计网课seo和sem哪个工资高
  • 返利网站开发葫岛百度seo
  • 网站建设基本流程视频惠州seo报价
  • 郑州网络推广联系方式泉州seo按天收费