【C++】检测TCP链接超时——时间轮组件设计
目录
引言
时间轮思想
设计的核心思路
完整代码
组件接口
个人主页:东洛的克莱斯韦克-CSDN博客
引言
对于高并发的服务器来说,链接是一种比较珍贵的资源,对不活跃的链接应该及时释放。判断连接是否活跃的策略是——在给定的时间内,该链接上并没有读事件,写事件,异常事件等。如果连接上有事件发生,则刷新链接的活跃时间。
而时间轮就可以高效的检测链接是否活跃,本文会带大家封装出一个时间轮的组件。
时间轮思想
时间轮的思想来源于钟表,钟表的时分秒指针指到特定的位置,就代表时间到了。参考钟表的策略,我们可用一个数组代表一个钟表,数组的下标代表时间,指向数组的指针按特定的时间向后移动,指针执行哪个位置,就代表哪个位置的时间到了。

相应的,指针1秒向后走一格,数组大小为60,这就是分级的时间轮。指针1分钟向后走一格,数组大小为60,这就是时级的时间轮。指针1小时向后走一格,数组大小为24,这就是天级的时间轮。
也就是说对于时间特别大的场景中,不需要很大的的空间。比如,一个任务在1天3小时15分5秒后超时(假设)只要天级时间轮指向1,就把该任务抛到时级时间轮中...以此类推。
设计的核心思路
我们需要两个关键的技术——析构函数,智能指针shared_ptr。
【C++】智能指针——auto_ptr,unique_ptr,shared_ptr_auto ptr-CSDN博客
在我们上述的阐述中,任务是有超时时间的,当时间轮的指针指向这个任务时,说明时间到了,我们该执行这个任务呢——答案是把任务的执行放到析构函数里。
时间轮的容器可以用两层vevtor—— std::vector<std::vector<TaskSharedPtr>>。如果指针指向TaskSharedPtr(任务类),就释放该类,该类的析构函数就会指向任务的回调。两次vevtor表示在同一个时间内可能会有多个任务。
智能指针shared_ptr用于任务类的超时时间刷新,在上文提到的高并发服务的场景中,如果触发了链接中的事件,就需要重新刷新时间,但时间轮的指针是一直向后移动的,任务类的下标迟早会被指到,然后该类就会被析构。
那么我们可以用shared_ptr管理任务类,并且新shared_ptr被插入时间轮之后正确的位置,有shared_ptr的引用计数在,任务类就不会被析构,时间也相当于刷新了。
完整代码
#include <functional>
#include <vector>
#include <memory>
#include <unordered_map>
#include <iostream>
#include <unistd.h>using TaskFunk = std::function<void()>; // 定时任务执行的方法
using CleanFunk = std::function<void()>; // 清理资源的回调
class TimerTask //任务类
{
private:uint64_t _id; // 任务对象的唯一性标识uint32_t _timeout_t; // 任务的超时时间bool _cancel; // 取消任务为true, 不取消为falseTaskFunk _taskfunk; // 要执行的任务CleanFunk _cleanfunk;public:TimerTask(uint64_t id, uint32_t timeout_t, const TaskFunk &funk): _id(id), _timeout_t(timeout_t), _cancel(false), _taskfunk(funk){}~TimerTask(){if (_cancel == false){_taskfunk();}_cleanfunk();}void AddCleanFunk(const CleanFunk &func){_cleanfunk = func;}uint32_t GetTimeout() // 获取超时时间{return _timeout_t;}void CancelTask() // 取消任务{_cancel = true;}
};class TimerWheel //时间轮
{
private:using TaskSharedPtr = std::shared_ptr<TimerTask>;using TaskWeakPtr = std::weak_ptr<TimerTask>;size_t _ptr; // 时间轮的指针size_t _capacity; // 时间轮的容量std::vector<std::vector<TaskSharedPtr>> _wheel; // 时间轮容器std::unordered_map<uint64_t, TaskWeakPtr> _v; // 任务id和任务weak_ptr映射的容器,快速索引,使shared_ptr引用计数加一
private:void CleanV(uint64_t id) // 清理_v容器资源的函数{auto t = _v.find(id);if (t != _v.end()){_v.erase(id);}}public:TimerWheel(size_t capacity): _ptr(0), _capacity(capacity), _wheel(capacity){}void AddTimerTask(uint64_t id, uint32_t timeout_t, const TaskFunk &funk) // 添加定时任务{TaskSharedPtr sp(new TimerTask(id, timeout_t, funk));TaskWeakPtr wp = sp;_v[id] = wp; // 向_v中注册sp->AddCleanFunk(std::bind(&TimerWheel::CleanV, this, id)); // 设置清理_v容器资源的回调size_t pos = (_ptr + sp->GetTimeout()) % _capacity;_wheel[pos].push_back(sp);}void UpdateTimerTask(uint64_t id) // 更新超时的时间{auto t = _v.find(id);if (t != _v.end()){TaskSharedPtr sp = _v[id].lock();size_t pos = (_ptr + sp->GetTimeout()) % _capacity;_wheel[pos].push_back(sp);}}void UpdatePtr() // 每隔?时间执行一次{_wheel[_ptr].clear();_ptr++;_ptr %= _capacity;}void CancelTask(uint64_t id) // 取消任务{auto t = _v.find(id);if (t != _v.end()){TaskSharedPtr sp = _v[id].lock();sp->CancelTask();}}
};
组件接口
AddTimerTask:向时间轮中注册任务,三个参数分别是任务id ,任务的超时时间,任务调用的方法。
在上层一定要确保任务id的唯一性。
UpdateTimerTask:传入任务id, 刷新超时时间
UpdatePtr: 这个接口就是前文说的时间轮的指针,多久调用一次就表示时间轮是一个什么级别的的时间轮
CancelTask:传入任务id,说明该任务在时间到了之后也不会被执行。
相关文章:
【C++】检测TCP链接超时——时间轮组件设计
目录 引言 时间轮思想 设计的核心思路 完整代码 组件接口 个人主页:东洛的克莱斯韦克-CSDN博客 引言 对于高并发的服务器来说,链接是一种比较珍贵的资源,对不活跃的链接应该及时释放。判断连接是否活跃的策略是——在给定的时间内&#…...
中国新媒体联盟与中运律师事务所 建立战略合作伙伴关系
2024年9月27日,中国新媒体联盟与中运律师事务所举行战略合作协议签字仪式。中国新媒体联盟主任兼中国社会新闻网主编、中法新闻法制网运营中心主任左新发,中运律师事务所高级顾问刘学伟代表双方单位签字。 中国新媒体联盟是由央视微电影中文频道联合多家…...
【ArcGIS微课1000例】0121:面状数据共享边的修改方法
文章目录 一、共享边概述二、快速的修改办法1. 整形共享边2. 修改边3. 概化边缘一、共享边概述 面状数据共享边指的是两个或多个面状数据(如多边形)共同拥有的边界。在地理信息系统(GIS)、三维建模、大数据分析等领域,面状数据共享边是描述面状空间数据拓扑关系的重要组成…...
图论(dfs系列) 9/27
一、二维网格图中探测环 题意: 给定一个二维数组grid,如果二维数组中存在一个环,处于环上的值都是相同的。返回true;如果不存在就返回false; 思路: 在以往的dfs搜索中,都是往四个方向去dfs;但是在这一道…...
如何在Windows上安装Docker
在 Windows 上使用 Docker 有两种主要方式:通过 Docker Desktop 安装并使用 WSL 2 作为后端,或者直接在 WSL 2 中安装 Docker。这里推荐手残党直接用图形界面安装到WSL 2的后端: 一、启用Hyper-V和容器特性 1. 右键Windows点击应用和功能 …...
golang格式化输入输出
fmt包使用类似于C的printf和scanf的函数实现格式化I/O 1输出格式化 一般的: 动词效果解释%v[1 -23 3]、[1 -23 3]、&{sdlkjf 23}以默认格式显示的值,与bool(%t)、int, int8 etc(%d)、uint, uint8 et…...
Jenkins基于tag的构建
文章目录 Jenkins参数化构建设置设置gitlab tag在工程中维护构建的版本按指定tag的版本启动服务 Jenkins参数化构建设置 选择参数化构建: 在gradle构建之前,增加执行shell的步骤: 把新增的shell框挪到gradle构建之前, 最后保存 …...
性能设计模式
class Singleton { public: static Singleton& getInstance() {static Singleton instance; // 局部静态变量return instance; } private:Singleton() {}Singleton(const Singleton&) delete; // 禁止拷贝Singleton& operator(const Singleton&) delete; // …...
Android 热点分享二维码功能简单介绍
Android 热点分享二维码 文章目录 Android 热点分享二维码一、前言二、热点二维码1、热点分享的字符串2、代码中热点字符串拼接和设置示例3、一个图片示例 三、其他1、Android 热点分享二维码小结2、Android11 设置默认热点名称和热点密码、密码长度 一、前言 比较新的Android…...
SIEM之王,能否克服创新者的窘境?
《网安面试指南》http://mp.weixin.qq.com/s?__bizMzkwNjY1Mzc0Nw&mid2247484339&idx1&sn356300f169de74e7a778b04bfbbbd0ab&chksmc0e47aeff793f3f9a5f7abcfa57695e8944e52bca2de2c7a3eb1aecb3c1e6b9cb6abe509d51f&scene21#wechat_redirect 《Java代码审…...
(JAVA)浅尝关于 “栈” 数据结构
1. 栈的概述: 1.1 生活中的栈 存储货物或供旅客住宿的地方,可引申为仓库、中转站。例如酒店,在古时候叫客栈,是供旅客休息的地方,旅客可以进客栈休息,休息完毕后就离开客栈 1.2计算机中的栈 将生活中的…...
【前端】ES13:ES13新特性
文章目录 1 类新增特性1.1 私有属性和方法1.2 静态成员的私有属性和方法1.3 静态代码块1.4 使用in来判断某个对象是否拥有某个私有属性 2 支持在最外层写await3 at函数来索引元素4 正则匹配的开始和结束索引5 findLast() 和 findLastIndex() 函数6 Error对象的Cause属性 1 类新…...
vuepress 浏览器加载缓存,总是显示旧页面,无法自动刷新数据的解决方法
vuepress 采用多页面形式,每个md文件在打包时,都会被转为一个html页面;而浏览器默认会缓存页面,导致更新的页面必须手动刷新才行 对于更新较为频繁的文档 全局可在config.js里设置 参考文档: https://vuepress.github.io/zh/ref…...
如何使用代理IP解决反爬虫问题
在网络爬虫的世界里,反爬虫机制就像是守卫城池的士兵,时刻准备着抵御外来的“入侵者”。为了突破这些守卫,代理IP就像是你的隐形斗篷,帮助你在网络世界中自由穿梭。今天,我们就来聊聊如何使用代理IP解决反爬虫问题。 …...
QT学习笔记之绘图
或许有人会等你到天黑,但是你不该在天黑后再找他(她)。 1.绘图事件 在ui文件中添加一个按钮,同时在资源文件中添加一个名字为1.jpg的图片。 widget.cpp #include "widget.h" #include "ui_widget.h" #incl…...
大数据新视界 --大数据大厂之数据清洗工具 OpenRefine 实战:清理与转换数据
💖💖💖亲爱的朋友们,热烈欢迎你们来到 青云交的博客!能与你们在此邂逅,我满心欢喜,深感无比荣幸。在这个瞬息万变的时代,我们每个人都在苦苦追寻一处能让心灵安然栖息的港湾。而 我的…...
基于QT的C++中小项目软件开发架构源码
描述 基于QT信号槽机制实现类之间的交互调用通信,适用于使用不同枚举作为消息交互的类型场景,支持附带任意参数,代码使用方式参考前一篇文章 特性 代码简洁,不超过100行仅需包含一个头文件Communicator.h,需要通信的…...
self-supervised, weakly supervised, and supervised respectively区别
Self-supervised learning(自监督学习)、weakly supervised learning(弱监督学习)和supervised learning(监督学习)是机器学习中的不同学习范式,它们的主要区别如下: 一、监督学习&…...
安卓好软-----手机屏幕自动点击工具 无需root权限
工具可以设置后自动点击屏幕。可以用于一些操作。例如自动刷视频等等哦 工具介绍 一款可以帮你实现自动操作的软件。软件中你可以根据实际需要设置点击位置,可以是屏幕上的特定位置,也可以是按钮或控件。功能非常强大,但是操作非常简单&…...
【Redis】主从复制(下)--主从复制原理和流程
文章目录 主从复制原理主从节点建立复制流程图数据同步 psyncpsync的语法格式 psync运行流程全量复制全量复制的流程全量复制的缺陷有磁盘复制 vs 无磁盘复制 部分复制部分复制的流程复制积压缓冲区 实时复制 主从复制原理 主从节点建立复制流程图 保存主节点的信息从节点(sla…...
谷歌浏览器插件
项目中有时候会用到插件 sync-cookie-extension1.0.0:开发环境同步测试 cookie 至 localhost,便于本地请求服务携带 cookie 参考地址:https://juejin.cn/post/7139354571712757767 里面有源码下载下来,加在到扩展即可使用FeHelp…...
Spark 之 入门讲解详细版(1)
1、简介 1.1 Spark简介 Spark是加州大学伯克利分校AMP实验室(Algorithms, Machines, and People Lab)开发通用内存并行计算框架。Spark在2013年6月进入Apache成为孵化项目,8个月后成为Apache顶级项目,速度之快足见过人之处&…...
基于Flask实现的医疗保险欺诈识别监测模型
基于Flask实现的医疗保险欺诈识别监测模型 项目截图 项目简介 社会医疗保险是国家通过立法形式强制实施,由雇主和个人按一定比例缴纳保险费,建立社会医疗保险基金,支付雇员医疗费用的一种医疗保险制度, 它是促进社会文明和进步的…...
FastAPI 教程:从入门到实践
FastAPI 是一个现代、快速(高性能)的 Web 框架,用于构建 API,支持 Python 3.6。它基于标准 Python 类型提示,易于学习且功能强大。以下是一个完整的 FastAPI 入门教程,涵盖从环境搭建到创建并运行一个简单的…...
爬虫基础学习day2
# 爬虫设计领域 工商:企查查、天眼查短视频:抖音、快手、西瓜 ---> 飞瓜电商:京东、淘宝、聚美优品、亚马逊 ---> 分析店铺经营决策标题、排名航空:抓取所有航空公司价格 ---> 去哪儿自媒体:采集自媒体数据进…...
AI病理诊断七剑下天山,医疗未来触手可及
一、病理诊断困局:刀尖上的医学艺术 1.1 金标准背后的隐痛 病理诊断被誉为"诊断的诊断",医生需通过显微镜观察组织切片,在细胞迷宫中捕捉癌变信号。某省病理质控报告显示,基层医院误诊率达12%-15%,专家会诊…...
nnUNet V2修改网络——暴力替换网络为UNet++
更换前,要用nnUNet V2跑通所用数据集,证明nnUNet V2、数据集、运行环境等没有问题 阅读nnU-Net V2 的 U-Net结构,初步了解要修改的网络,知己知彼,修改起来才能游刃有余。 U-Net存在两个局限,一是网络的最佳深度因应用场景而异,这取决于任务的难度和可用于训练的标注数…...
通过MicroSip配置自己的freeswitch服务器进行调试记录
之前用docker安装的freeswitch的,启动是正常的, 但用下面的Microsip连接不上 主要原因有可能一下几个 1、通过下面命令可以看 [rootlocalhost default]# docker exec -it freeswitch fs_cli -x "sofia status profile internal"Name …...
jdbc查询mysql数据库时,出现id顺序错误的情况
我在repository中的查询语句如下所示,即传入一个List<intager>的数据,返回这些id的问题列表。但是由于数据库查询时ID列表的顺序与预期不一致,会导致返回的id是从小到大排列的,但我不希望这样。 Query("SELECT NEW com…...
C# winform教程(二)----checkbox
一、作用 提供一个用户选择或者不选的状态,这是一个可以多选的控件。 二、属性 其实功能大差不差,除了特殊的几个外,与button基本相同,所有说几个独有的 checkbox属性 名称内容含义appearance控件外观可以变成按钮形状checkali…...
