【仿muduo庫實現并發服務器】Poller模塊

仿muduo庫實現并發服務器

  • 1.Poller模塊
    • 成員變量
    • 創建epoll模型
    • 對于一個描述符添加或修改事件監控
    • 對于一個描述符移除事件監控
    • 啟動epoll事件監控,獲取所有活躍連接

1.Poller模塊

Poller模塊主要是對任意的描述符進行IO事件監控。
它是對epoll的封裝,可以讓對描述符進行事件監控的操作更加簡單。

它與Channel的關系:
一旦有活躍事件了,只有獲取到這個連接的Channel對象,才能知道該連接要監控的事件是什么,知道事件就緒如何去處理。

主要的流程:
1.對描述符進行監控,但是要注意監控的對象是channel對象,因為只有channel對象才能找到該描述符要監控什么事件。
2.當描述符就緒時,通過描述符映射找到channel對象(通過hash找到channel對象),因為只有找到channel對象,才能知道就緒的事件如何處理。所以當描述符就緒時,就返回對應的channel對象。

成員變量

private:int _epfd;                                   // 用來標識epoll模型struct epoll_event _evs[DEFALUTMAX];         // 用來保存所有就緒的事件信息,信息1:就緒的描述符fd是誰。信息2:就緒的事件是什么std::unordered_map<int, Channel *> _channel; // 用來保存所有要監控的描述符信    

1.poller是封裝epoll對描述符進行操作,所以一定要有一個epoll句柄。
2.當事件就緒時,就緒的事件信息就會保存在struct epoll_event 結構體數據中,保存的信息有就緒的描述符fd,就緒的事件。
3.poller是用來監控管理所有要監控的描述符,所以需要一個容器保存所有監控的描述符。
而poller監控的對象是channel,所以使用hash通過描述符映射對應的channel。這樣就可以保存管理所有監控的描述符對象。

創建epoll模型

創建epoll模型,使用epoll_create()接口,返回值就是對應的epoll句柄。

// 創建epoll模型Poller(){_epfd = epoll_create(DEFALUTMAX); // 創建一個epoll模型if (_epfd < 0){ERRLog("epoll create failed");abort(); // 這個出錯了就直接退出}}

對于一個描述符添加或修改事件監控

對描述符進行添加或修改事件監控,需要使用的接口是epoll_ctl(),不過這里對epoll_ctl()的操作先封裝起來,外部直接調用這個封裝好的epoll_ctl接口

要想對一個描述符添加事件監控,首先需要知道該描述符的fd,要監控的事件是什么,要進行操作是什么等細節。而描述符的fd,以及要監控的事件是什么都在channel對象里,所以傳入一個channel對象,以及所需要進行操作即可。

不過在對一個連接真正添加和修改或者移除事件之前,還是需要判斷一個該連接是否已經被添加到內核里面去了,如果已經被添加進去了,那么要進行的操作就是更新修改了,就不是添加了。所以我們還需要封裝一個判定是否已經設置了監控的接口。
如何判斷呢?就判斷管理的哈希表中是否存在對于的channel對象即可。

 // 直接對epoll_ctl進行操作void Update(Channel *channel, int op){int fd = channel->Fd();//獲取該channnel對應的描述符fdstruct epoll_event ev;ev.data.fd = fd;//設置要關系的fdev.events = channel->Events();//設置要關系的事件int ret = epoll_ctl(_epfd, op, fd, &ev);//對于一個描述符進行添加或修改事件監控if (ret < 0){ERRLog("epoll_ctl failed");}}// 判斷一個連接channel是否設置了事件監控,就看_channel中是否有該連接bool HasChannel(Channel *channel){auto it = _channel.find(channel->Fd());if (it == _channel.end())return false; // 沒找到return true;}

所以在內部封裝了兩個接口,對外真正提供的接口則是:

// 對于一個描述符添加或修改事件監控void UpdateEvent(Channel *channel){// 首先判斷該連接是否已經被設置監控了,如果沒有則添加監控,如果有則進行修改if (HasChannel(channel) == false){_channel.insert(std::make_pair(channel->Fd(), channel));//_channel[channel->Fd()]=channel;Update(channel, EPOLL_CTL_ADD);//}else{Update(channel, EPOLL_CTL_MOD);}}

對于一個描述符移除事件監控

對于描述符進行移除事件監控,主要有兩個步驟:
1.從管理的hash表里移除(erase)
2.從紅黑色樹上移除(epoll_ctl,DEL)

 // 對于一個描述符移除事件監控void RemoveEvent(Channel *channel){auto it = _channel.find(channel->Fd());//在哈希表中找到該channel對象if (it != _channel.end()){_channel.erase(it);//從哈希表中刪除該channnel對象}Update(channel, EPOLL_CTL_DEL);//從內核中刪除該監控}

啟動epoll事件監控,獲取所有活躍連接

啟動事件監控,就是epoll進行等待事件就緒。
當有事件就緒時,epoll就不再等待,就會返回,并將就緒的信息帶回來。
就緒的信息有哪個文件描述符的什么事件就緒了,光有這些信息是沒有用的,因為對于描述符的channel對象不知道什么事件就緒啊,只有channel對象才能知道就緒后該怎么操作。所以需要將該描述符的什么事件就緒信息設置進對應的channel對象中(通過描述符在哈希表中映射找到channel對象),這樣channel對象才能知道它就緒了什么事件,并且可以進行對應的處理,
所以我們可以通過一個vector數組,將所有就緒的channel對象全部存儲起來。
供外層eventloop取出,全部依次執行對應的操作。
操作:
1.epoll進行等待監控
2.epoll返回,將就緒的信息設置到對應的channel對象中
3.保存所有就緒的channel對象。
通過一個輸出型參數將數據帶出來。

 // 開始監控,并返回所有活躍連接void Poll(std::vector<Channel *> *active){int nfds = epoll_wait(_epfd, _evs, DEFALUTMAX, -1); // 默認為阻塞等待if (nfds < 0){if (errno == EINTR){return;}ERRLog("epoll wait failed:%s\n", strerror(errno));abort();}for (int i = 0; i < nfds; i++)//有事件就緒了{int fd = _evs[i].data.fd;                    // 活躍的fd是哪個、assert(_channel.find(fd) != _channel.end()); // 不能在管理的channel里找不到// 找到之后就將就緒的事件信息設置到對應的channel里_channel[fd]->SetRevents(_evs[i].events);active->push_back(_channel[fd]); // 將活躍的連接插入進去,保存起來}}

本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。
如若轉載,請注明出處:http://www.pswp.cn/news/913066.shtml
繁體地址,請注明出處:http://hk.pswp.cn/news/913066.shtml
英文地址,請注明出處:http://en.pswp.cn/news/913066.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

小程序學習筆記:使用 MobX 實現全局數據共享,實例創建、計算屬性與 Actions 方法

在小程序開發過程中&#xff0c;組件間的數據共享是一個常見且關鍵的問題。今天&#xff0c;我們就來深入探討一下如何在小程序中實現全局數據共享&#xff0c;借助 MobX 相關的包&#xff0c;讓數據管理變得更加高效便捷。 什么是全局數據共享 全局數據共享&#xff0c;也被…

觀測云 × AWS SSO:權限治理可觀測實踐

AWS IAM Identity Center 介紹 AWS IAM Identity Center&#xff08;原 AWS Single Sign-On&#xff09;是 AWS 提供的一項云原生身份與訪問管理&#xff08;IAM&#xff09;服務&#xff0c;旨在集中簡化多 AWS 賬戶、多業務應用的安全訪問控制。 觀測云 觀測云是一款專為 …

springboot整合配置swagger3

一. swagger3介紹 Swagger 3 是基于 OpenAPI 規范 3.0 的 API 文檔工具&#xff0c;用于設計、構建和消費 RESTful API。它通過標準化描述 API 的接口、參數、響應等元數據&#xff0c;實現以下核心功能&#xff1a; 自動生成交互式文檔API 測試與調試代碼生成&#xff08;客…

RabbitMQ 4.1.1初體驗

為什么選擇 RabbitMQ&#xff1f;* RabbitMQ 是一款可靠且成熟的消息代理和流處理中間件&#xff0c;可輕松部署在云端、本地數據中心或您的開發機上&#xff0c;目前已被全球數百萬用戶使用。 優勢在哪里 互操作性 RabbitMQ 支持多種開放標準協議&#xff0c;包括 AMQP 1.0 和…

【精華】QPS限流等場景,Redis其他數據結構優劣勢對比

下面是一個詳細的 Redis 數據結構對比表&#xff0c;比較它們在實現 QPS 限流 / 滑動窗口統計 / 查定比監控等場景中的適用性&#xff1a; ? Redis 數據結構對比表&#xff08;用于接口限流 / QPS 監控&#xff09; 維度String INCR 固定窗口List 滑動窗口Hash 計數器ZSet 滑…

頂層設計:支持單元化、灰度化的應用架構

一、頂層目標 業務連續性&#xff1a;任何單元故障不影響整體彈性伸縮&#xff1a;根據業務流量橫向擴展靈活灰度&#xff1a;任何發布都可逐步平滑上線成本可控&#xff1a;單元化帶來的資源冗余最小 二、核心理念 設計目標核心理念單元化垂直拆分&#xff0c;分而治之&…

MacOS Safari 如何打開F12 開發者工具 Developer Tools

背景 If you’re a web develper, the Safari Develop menu provides tools you can use to make sure your website works well with all standards-based web browsers. 解決 If you don’t see the Develop menu in menu bar, Choose Safari > settingsClick Advanced…

2025—暑期訓練一

A 本題描述了一個最優路徑規劃問題的解法&#xff0c;核心思路是利用數軸上區間覆蓋的特性&#xff0c;將問題簡化為兩個端點的訪問問題。以下是關鍵點的詳細解析&#xff1a; 核心觀察 區間覆蓋特性 給定的位置數組 x1, x2, ..., xn 是嚴格遞增的&#xff08;即 x1 < x2 …

ubuntu 18.04配置鏡像源

配置鏡像源的主要作用是優化軟件下載速度、提升系統更新穩定性&#xff0c;并確保軟件包獲取的可靠性 我這里配置阿里云鏡像源 鏡像的具體內容參考此文: 文章鏈接 以防萬一,先備份一下 sudo cp /etc/apt/sources.list /etc/apt/sources.list.bak然后開始修改 sudo nano /etc…

RecyclerView中跳轉到最后一條item并確保它在可視區域內顯示

在RecyclerView中跳轉并顯示最后一條Item 要在RecyclerView中跳轉到最后一條item并確保它在可視區域內顯示&#xff0c;可以使用以下幾種方法&#xff1a; 1. 使用scrollToPosition()方法&#xff08;基本方法&#xff09; recyclerView.scrollToPosition(adapter.getItemCo…

ubuntu22 桌面版開啟root登陸

一、先創建root sudo passwd root 二、注釋代碼 vim /etc/pam.d/gdm-password vim/etc/pam.d/gdm-autologin 都注釋 auth required pam_succeed_if.so user ! root quiet_success 三、修改profile文件 vim /root/.profile 注釋掉 mesg n 2&#xff1e; /dev/null || true 插入新…

docker學習二天之鏡像操作與容器操作

鏡像的一般運用過程 一、鏡像&#xff08;Image&#xff09;操作 鏡像是容器的基礎模板&#xff0c;存儲在本地或遠程倉庫中。 1. 鏡像拉取 # 從指定鏡像源拉取 docker pull docker.m.daocloud.io/library/nginx 2. 鏡像查看 # 列出本地鏡像 docker images # 或 docker image…

多個參數用websocket 向io 服務器發送變量,一次發一個,并接收響應

問題&#xff1a;多個參數用websocket 向io 服務器發送變量&#xff0c;一次發一個&#xff0c;并接收響應&#xff0c;如果是多個變量&#xff0c;但還是需要一個個發送&#xff0c;應該怎么實現&#xff0c;思路是什么樣子的呢&#xff1f;用數組的話&#xff0c;應該怎么用&…

Flink-05學習 接上節,將FlinkJedisPoolConfig 從Kafka寫入Redis

上節成功實現了FlinkKafkaConsumer消費Kafka數據&#xff0c;并將數據寫入到控制臺&#xff0c;接下來將繼續將計算的結果輸入到redis中。 pom.xml 引入redis到pom包 <?xml version"1.0" encoding"UTF-8"?> <project xmlns"http://mave…

git教程-pycharm使用tag打標簽

一.生成tag標簽 前言 當我們的代碼完成了第一階段的需求&#xff0c;版本穩定后&#xff0c;希望能出個穩定版本。于是在 commit 后需要打個 tag 標簽&#xff0c;也就是我們平常說的版本號&#xff0c;如v1.0版本 本篇講解如何使用 pycharm 打 tag 標簽&#xff0c;并推送到…

PHP Error: 深入解析與處理技巧

PHP Error: 深入解析與處理技巧 引言 PHP作為一種廣泛使用的服務器端腳本語言,在Web開發領域占據著重要地位。然而,任何編程語言都難以避免錯誤的發生。本文將深入探討PHP錯誤處理的相關知識,包括錯誤類型、錯誤顯示、錯誤日志以及錯誤處理技巧,幫助開發者更好地應對和解…

21、企業行政辦公(OA)數字化轉型:系統如何重塑企業高效運營新范式

企業行政辦公是營造高效工作環境、提升員工幸福感和歸屬感的重要基石&#xff0c;更是傳遞組織溫度與價值關懷的第一窗口。在數字化轉型浪潮席卷各行各業的今天&#xff0c;企業行政辦公領域正經歷一場靜默但深刻的變革。據統計&#xff0c;采用智能化OA系統的企業&#xff0c;…

基于開源AI智能名片鏈動2+1模式S2B2C商城小程序的抖音渠道力拓展與多渠道利潤增長研究

摘要&#xff1a;在數字化商業競爭日益激烈的背景下&#xff0c;抖音平臺憑借其龐大的流量基礎和興趣電商生態&#xff0c;成為品牌增長的關鍵陣地。渠道力作為品牌增長的核心驅動力&#xff0c;以抖音勢能為內核&#xff0c;通過流量與銷量的外溢效應&#xff0c;可顯著提升品…

基于二維碼的視頻合集高效管理與分發技術

一、 視頻資源聚合的技術挑戰與解決方案 在企業培訓、在線教育和產品展示等場景中&#xff0c;視頻資源的結構化組織與高效分發始終是技術實現的核心挑戰。傳統方案往往面臨三大痛點&#xff1a;資源碎片化導致的管理混亂、多視頻序列播放的用戶體驗不佳、以及跨平臺兼容性問題…

GPT-2論文閱讀:Language Models are Unsupervised Multitask Learners

本文解析 OpenAI 2019 年發布的里程碑式論文&#xff0c;該論文首次提出了 GPT-2 模型&#xff0c;揭示了語言模型作為無監督多任務學習器的革命性潛力。文章的核心觀點是&#xff1a;語言模型在無監督訓練過程中&#xff0c;可以隱式地學習多種任務&#xff0c;無需特定任務微…