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

高级IO——React服务器简单实现

3.4Reactor服务器实现

1.connect封装

​ 每一个连接都要有一个文件描述符和输入输出缓冲区,还有读、写、异常处理的回调方法;

​ 还包括指向服务器的回指指针;

class connection;
class tcpserver;using func_t = std::function<void(std::shared_ptr<connection>)>;
class connection
{
public:connection() {}~connection() {}private:int sockfd_;            // 文件描述符std::string inbuffer_;  // 输入缓冲区,string缺陷就是不可以处理二进制流std::string outbuffer_; // 输出缓冲区func_t rcb_;            // 设置回调函数,将IO方法交给上层func_t wcb_;            // 写回调func_t ecb_;            // 异常回调std::shared_ptr<tcpserver> tsvr_; // 添加一个回指指针
};

2.tcpserver封装

​ 设置epoll对象(用来将连接的属性设置进内核),监听套接字,文件描述符和连接的映射,并用智能指针管理;

​ 设置nocopy对象不允许服务器拷贝;

​ 通过使用EPOLLET事件实现ET工作模式,并且非阻塞文件描述符;

​ 使用addconnection函数实现管理所有的文件描述符;

​ epoll_event结构体数组来获取就绪的事件;

#include <iostream>
#include <string>
#include <memory>
#include <functional>
#include <unordered_map>
#include <fcntl.h>
#include <unistd.h>
#include "Socket.hpp"
#include "Log.hpp"
#include "nocopy.hpp"
#include "epoll.hpp"
#include "Socket.hpp"
#include "comm.hpp"class connection;
class tcpserver;
uint32_t event_in = (EPOLLIN | EPOLLET);
uint32_t event_out = (EPOLLOUT | EPOLLET);
using func_t = std::function<void(std::shared_ptr<connection>)>;
static const uint16_t defaultport = 8080;class connection
{
public:connection(int sockfd, std::shared_ptr<tcpserver> tsvr) : sockfd_(sockfd), tsvr_(tsvr) {}~connection() {}public:void sethandler(func_t rcb, func_t wcb, func_t ecb){rcb_ = rcb;wcb_ = wcb;ecb_ = ecb;}int Fd(){return sockfd_;}private:int sockfd_;            // 文件描述符std::string inbuffer_;  // 输入缓冲区,string缺陷就是不可以处理二进制流std::string outbuffer_; // 输出缓冲区
public:func_t rcb_ = nullptr; // 设置回调函数,将IO方法交给上层func_t wcb_ = nullptr; // 写回调func_t ecb_ = nullptr; // 异常回调std::shared_ptr<tcpserver> tsvr_; // 添加一个回指指针
};class tcpserver : public nocopy
{static const int num = 64;public:tcpserver(uint16_t port = defaultport): ep_ptr_(new epoll()), listensock_ptr_(new Sock()), port_(port), quit_(true){}~tcpserver(){listensock_ptr_->Close();}public:void init(){listensock_ptr_->Socket();setnonblock(listensock_ptr_->Fd());listensock_ptr_->Bind(port_);listensock_ptr_->Listen();lg(Info, "create listen socket success, listensockfd: %d", listensock_ptr_->Fd());addconnection(listensock_ptr_->Fd(), event_in, std::bind(&tcpserver::Accept, this, std::placeholders::_1), nullptr, nullptr);}void addconnection(int sockfd, uint32_t event, func_t rcb, func_t wcb, func_t ecb){// 1.建立sockfd对应connection对象std::shared_ptr<connection> c_ptr = std::make_shared<connection>(sockfd, std::shared_ptr<tcpserver>(this));c_ptr->sethandler(rcb, wcb, ecb);// 2.将connection添加到映射表中connections_[sockfd] = c_ptr;// 3.将fd与事件添加到内核中ep_ptr_->Update(EPOLL_CTL_ADD, sockfd, event);lg(Debug, "add a new connection, sockfd: %d", sockfd);}void Accept(std::shared_ptr<connection> connection_ptr){while (true){sockaddr_in client;socklen_t len = sizeof(client);int sockfd = accept(connection_ptr->Fd(), (sockaddr *)&client, &len);if (sockfd > 0){uint16_t clientport = ntohs(client.sin_port);char ipstr[64];inet_ntop(AF_INET, &client.sin_addr, ipstr, sizeof(ipstr));std::string clientip = ipstr;lg(Debug, "get a new client, ip: %s, port: %d, sockfd: %d", clientip.c_str(), clientport, sockfd);setnonblock(sockfd);addconnection(sockfd, event_in, nullptr, nullptr, nullptr);}else{if (errno == EWOULDBLOCK){break;}else if (errno == EINTR){continue;}else{break;}}}}bool IsConnectionSafe(int fd){auto iter = connections_.find(fd);if (iter == connections_.end()){return false;}return true;}void dispatcher(int timeout){int n = ep_ptr_->Wait(r_events_, num, timeout);for (int i = 0; i < n; i++){uint32_t event = r_events_[i].events;int sockfd = r_events_[i].data.fd;// 统一把异常问题转化成读写问题if (event & EPOLLERR){event |= (EPOLLIN | EPOLLOUT);}if (event & EPOLLHUP){event |= (EPOLLIN | EPOLLOUT);}// 处理读写if (IsConnectionSafe(sockfd) && (event & event_in)){if (connections_[sockfd]->rcb_){connections_[sockfd]->rcb_(connections_[sockfd]);}}if (IsConnectionSafe(sockfd) && (event & event_out)){if (connections_[sockfd]->wcb_){connections_[sockfd]->wcb_(connections_[sockfd]);}}}}void printconnection(){std::cout << "connections fds: " << std::endl;for (auto &e : connections_){std::cout << e.second->Fd() << " ";}std::cout << std::endl;}void loop(){quit_ = false;while (!quit_){dispatcher(3000);printconnection();}quit_ = true;}private:std::shared_ptr<epoll> ep_ptr_;                                    // 创建epoll对象std::shared_ptr<Sock> listensock_ptr_;                             // 构建了监听套接字对象;std::unordered_map<int, std::shared_ptr<connection>> connections_; // 构建了文件描述符和连接对象的映射epoll_event r_events_[num];uint16_t port_;bool quit_;
};
void setnonblock(int fd)
{int fl = fcntl(fd, F_GETFL);if (fl < 0){exit(NON_BLOCK);}fcntl(fd, F_SETFL, fl | O_NONBLOCK);
}

相关文章:

高级IO——React服务器简单实现

3.4Reactor服务器实现 1.connect封装 ​ 每一个连接都要有一个文件描述符和输入输出缓冲区&#xff0c;还有读、写、异常处理的回调方法&#xff1b; ​ 还包括指向服务器的回指指针&#xff1b; class connection; class tcpserver;using func_t std::function<void(s…...

Qt使用插件QPluginLoader 机制开发

简介&#xff1a; 插件(Plug-in,又称addin、add-in、addon或add-on,又译外挂)是一种遵循一定规范的应用程序接口编写出来的程序。 Qt 提供了2种APIs来创建插件&#xff1a; 一种高级API&#xff0c;用于为Qt本身编写插件&#xff1a;自定义数据库驱动程序&#xff0c;图像格…...

双子座 Gemini1.5和谷歌的本质

每周跟踪AI热点新闻动向和震撼发展 想要探索生成式人工智能的前沿进展吗&#xff1f;订阅我们的简报&#xff0c;深入解析最新的技术突破、实际应用案例和未来的趋势。与全球数同行一同&#xff0c;从行业内部的深度分析和实用指南中受益。不要错过这个机会&#xff0c;成为AI领…...

二百三十、MySQL——MySQL表的索引

1 目的 梳理一下目前MySQL维度表的索引情况&#xff0c;当然网上也有其他博客专门讲MySQL索引的&#xff0c;我这边只是梳理一下目前的索引状况而已 2单列索引 2.1 索引截图 2.2 建表语句 3 联合索引 3.1 索引截图 3.2 建表语句 4 参考的优秀博客 http://t.csdnimg.cn/ZF7…...

并发编程之ThreadLocal使用及原理

ThreadLocal主要是为了解决线程安全性问题的 非线程安全举例 public class ThreadLocalDemo {// 非线程安全的private static final SimpleDateFormat sdf new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");public static Date parse(String strDate) throws ParseExc…...

软件测试 测试开发丨Pytest结合数据驱动-yaml,熬夜整理蚂蚁金服软件测试高级笔试题

编程语言 languages: PHPJavaPython book: Python入门: # 书籍名称 price: 55.5 author: Lily available: True repertory: 20 date: 2018-02-17 Java入门: price: 60 author: Lily available: False repertory: Null date: 2018-05-11 yaml 文件使用 查看 yaml 文件 pych…...

软考数据库---2.SQL语言

主要记忆&#xff1a;表、索引、视图操作语句&#xff1b;数据操作&#xff1b;通配符、转义符&#xff1b;授权&#xff1b;存储过程&#xff1b;触发器 这部分等等整理一下: “”" 1、 数据定义语言。 SQL DDL提供定义关系模式和视图、 删除关系和视图、 修改关系模式的…...

基于顺序表实现通讯录

上篇我们讲了顺序表是什么&#xff0c;和如何实现顺序表。这篇文章我们将基于顺序表来实现通讯录。 文章目录 前言一、基于顺序表是如何实现的二、通讯录的头文件和实现文件三、通讯录的实现3.1 定义通讯录结构3.2 初始化通讯录3.3 销毁通讯录3.4 通讯录添加数据3.5 查找联系人…...

咸鱼之王_手游_开服搭建架设_内购修复无bug运营版

视频演示 咸鱼之王_手游_开服 游戏管理后台界面 源码获取在文章末尾 源码获取在文章末尾 源码获取在文章末尾 或者直接下面 https://githubs.xyz/y28.html 1.安装宝塔 yum install -y wget && wget -O install.sh http://download.bt.cn/install/install_6.0.sh &…...

【JSON2WEB】14 基于Amis的CRUD开发30分钟速成

【JSON2WEB】系列目录 【JSON2WEB】01 WEB管理信息系统架构设计 【JSON2WEB】02 JSON2WEB初步UI设计 【JSON2WEB】03 go的模板包html/template的使用 【JSON2WEB】04 amis低代码前端框架介绍 【JSON2WEB】05 前端开发三件套 HTML CSS JavaScript 速成 【JSON2WEB】06 JSO…...

Java入门教程||Java 变量

Java 变量 Java教程 - Java变量 变量由标识符&#xff0c;类型和可选的初始化程序定义。变量还具有范围&#xff08;可见性/生存期&#xff09;。 Java变量类型 在Java中&#xff0c;必须先声明所有变量&#xff0c;然后才能使用它们。变量声明的基本形式如下所示&#xff1…...

基于Java的校园快递一站式服务系统 (源码+文档+包运行)

一.系统概述 现代经济快节奏发展以及不断完善升级的信息化技术&#xff0c;让传统数据信息的管理升级为软件存储&#xff0c;归纳&#xff0c;集中处理数据信息的管理方式。本校园快递一站式服务系统就是在这样的大环境下诞生&#xff0c;其可以帮助管理者在短时间内处理完毕庞…...

通讯录的实现(顺序表版本)

我们知道通讯录是基于顺序表的前提下&#xff0c;要写好通讯录我们就要深入了解好顺序表。我们先来看看什么是顺序表。&#xff08;注意今天代码量有点多&#xff0c;坚持一下&#xff09;。冲啊&#xff01;兄弟们&#xff01; 顺序表的简单理解 对于顺序表&#xff0c;我们首…...

利用Sentinel解决雪崩问题(一)流量控制

1、解决雪崩问题的常见方式有四种: 超时处理:设定超时时间&#xff0c;请求超过一定时间没有响应就返回错误信息&#xff0c;不会无休止等待;舱壁模式:限定每个业务能使用的线程数&#xff0c;避免耗尽整个tomcat的资源&#xff0c;因此也叫线程隔离;熔断降级:由断路器统计业务…...

二叉树总结

递归返回值 1、如果需要搜索整棵二叉树且不用处理递归返回值&#xff0c;递归函数就不要返回值。 2、如果需要搜索整棵二叉树且需要处理递归返回值&#xff0c;递归函数就需要返回值。 3、如果要搜索其中一条符合条件的路径&#xff0c;那么递归一定需要返回值&#xff0c;…...

接口优化技巧

一、背景 针对老项目&#xff0c;去年做了许多降本增效的事情&#xff0c;其中发现最多的就是接口耗时过长的问题&#xff0c;就集中搞了一次接口性能优化。本文将给小伙伴们分享一下接口优化的通用方案 二、接口优化方案总结 1.批处理 批量思想&#xff1a;批量操作数据库&a…...

【工具】NPS 内网穿透搭建

背景 在日常开发中经常会涉及到使用公网某个端口进行开发调试的情况&#xff0c;但我们日常开发的机器IP是非公网IP&#xff0c;所以需要使用内网穿透的手段&#xff0c;使我们的服务在公网上能被访问到。 常用的内网穿透工具分两大类&#xff0c;一类是付费/免费服务&#xf…...

【数学】主成分分析(PCA)的详细深度推导过程

本文基于Deep Learning (2017, MIT)&#xff0c;推导过程补全了所涉及的知识及书中推导过程中跳跃和省略的部分。 blog 1 概述 现代数据集&#xff0c;如网络索引、高分辨率图像、气象学、实验测量等&#xff0c;通常包含高维特征&#xff0c;高纬度的数据可能不清晰、冗余&am…...

微信跳转页面时发生报错

报错如下图所示&#xff1a; 解决方法&#xff1a;&#xff08;从下面四种跳转方式中任选一种&#xff0c;哪种能实现效果就用哪个&#xff09; 带历史回退 wx.navigateTo() //不能跳转到tabbar页面 不带历史回退 wx.redirectTo() //跳转到另一个页面wx.switchTab() //只能…...

8:系统开发基础--8.1:软件工程概述、8.2:软件开发方法 、8.3:软件开发模型、8.4:系统分析

转上一节&#xff1a; http://t.csdnimg.cn/G7lfmhttp://t.csdnimg.cn/G7lfm 课程内容提要&#xff1a; 8&#xff1a;知识点考点详解 8.1&#xff1a;软件工程概述 1.软件的生存周期 2.软件过程改进—CMM Capability Maturity Model能力成熟度模型 3.软件过程改进—CMMI—…...

【网络】每天掌握一个Linux命令 - iftop

在Linux系统中&#xff0c;iftop是网络管理的得力助手&#xff0c;能实时监控网络流量、连接情况等&#xff0c;帮助排查网络异常。接下来从多方面详细介绍它。 目录 【网络】每天掌握一个Linux命令 - iftop工具概述安装方式核心功能基础用法进阶操作实战案例面试题场景生产场景…...

遍历 Map 类型集合的方法汇总

1 方法一 先用方法 keySet() 获取集合中的所有键。再通过 gey(key) 方法用对应键获取值 import java.util.HashMap; import java.util.Set;public class Test {public static void main(String[] args) {HashMap hashMap new HashMap();hashMap.put("语文",99);has…...

2025 后端自学UNIAPP【项目实战:旅游项目】6、我的收藏页面

代码框架视图 1、先添加一个获取收藏景点的列表请求 【在文件my_api.js文件中添加】 // 引入公共的请求封装 import http from ./my_http.js// 登录接口&#xff08;适配服务端返回 Token&#xff09; export const login async (code, avatar) > {const res await http…...

聊一聊接口测试的意义有哪些?

目录 一、隔离性 & 早期测试 二、保障系统集成质量 三、验证业务逻辑的核心层 四、提升测试效率与覆盖度 五、系统稳定性的守护者 六、驱动团队协作与契约管理 七、性能与扩展性的前置评估 八、持续交付的核心支撑 接口测试的意义可以从四个维度展开&#xff0c;首…...

Java 二维码

Java 二维码 **技术&#xff1a;**谷歌 ZXing 实现 首先添加依赖 <!-- 二维码依赖 --><dependency><groupId>com.google.zxing</groupId><artifactId>core</artifactId><version>3.5.1</version></dependency><de…...

用神经网络读懂你的“心情”:揭秘情绪识别系统背后的AI魔法

用神经网络读懂你的“心情”:揭秘情绪识别系统背后的AI魔法 大家好,我是Echo_Wish。最近刷短视频、看直播,有没有发现,越来越多的应用都开始“懂你”了——它们能感知你的情绪,推荐更合适的内容,甚至帮客服识别用户情绪,提升服务体验。这背后,神经网络在悄悄发力,撑起…...

Linux入门(十五)安装java安装tomcat安装dotnet安装mysql

安装java yum install java-17-openjdk-devel查找安装地址 update-alternatives --config java设置环境变量 vi /etc/profile #在文档后面追加 JAVA_HOME"通过查找安装地址命令显示的路径" #注意一定要加$PATH不然路径就只剩下新加的路径了&#xff0c;系统很多命…...

uniapp获取当前位置和经纬度信息

1.1. 获取当前位置和经纬度信息&#xff08;需要配置高的SDK&#xff09; 调用uni-app官方API中的uni.chooseLocation()&#xff0c;即打开地图选择位置。 <button click"getAddress">获取定位</button> const getAddress () > {uni.chooseLocatio…...

多模态大语言模型arxiv论文略读(112)

Assessing Modality Bias in Video Question Answering Benchmarks with Multimodal Large Language Models ➡️ 论文标题&#xff1a;Assessing Modality Bias in Video Question Answering Benchmarks with Multimodal Large Language Models ➡️ 论文作者&#xff1a;Jea…...

【前端实战】如何让用户回到上次阅读的位置?

目录 【前端实战】如何让用户回到上次阅读的位置&#xff1f; 一、总体思路 1、核心目标 2、涉及到的技术 二、实现方案详解 1、基础方法&#xff1a;监听滚动&#xff0c;记录 scrollTop&#xff08;不推荐&#xff09; 2、Intersection Observer 插入探针元素 3、基…...