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

基于多反应堆的高并发服务器【C/C++/Reactor】(中)创建并初始化TcpServer实例 以及 启动

对于一个TcpServer来说,它的灵魂是什么?就是需要提供一个事件循环EventLop(EventLoop),不停地去检测有没有客户端的连接到达,有没有客户端给服务器发送数据,描述的这些动作,反应堆模型能够胜任。当服务器和客户端建立连接之后,剩下的就是网络通信,在通信的时候,需要把接收的数据和要发送的数据存储到一块内存里边,Buffer(Buffer)就是为此量身定制的。另外,如果服务器想和客户端实现并发操作,需要用到多线程。我们提供了线程池ThreadPool(ThreadPool),剩下的事就是把服务器模型里边的代码实现一下,基于服务器的整体流程实现一下TcpConnection

这个TcpConnection就是服务器和客户端建立连接之后,它们是在通信的时候,其实就需要用到Http,如果想要实现一个HttpServer,就需要用到Http协议,再把HttpRequestHttpResponse写出来之后,整个项目的流程就全部走通了。

TcpServer分为几个部分:

  1. 主线程需要有一个Listener(包括端口port,监听的文件描述符listenFd
  2. 主线程的事件循环MainEventLoop(反应堆)
  3. 一个线程池ThreadPool
  4. TcpConnection其实是子线程的任务。服务器与客户端建立连接之后,子线程要是想工作的话,就必须创建一个TcpConnection实例。如果没有这个TcpConnection模块,子线程就不知道在建立连接之后需要做什么事情
struct Listener {int lfd;unsigned short port;
};struct TcpServer {struct Listener* listener; // 监听套接字struct EventLoop* mainLoop; // 主线程的事件循环(反应堆模型)struct ThreadPool* threadPool; // 线程池int threadNum; // 线程数量
};

一、创建并初始化TcpServer实例

(1)初始化监听

// 初始化监听
struct Listener* listenerInit(unsigned short port);
// 初始化监听
struct Listener* listenerInit(unsigned short port) {// 创建一个Listner实例 -> listenerstruct Listener* listener = (struct Listener*)malloc(sizeof(struct Listener));// 1.创建一个监听的文件描述符 -> lfdint lfd = socket(AF_INET,SOCK_STREAM,0); // AF_INET -> (网络层协议:Ipv4) ;SOCK_STREAM -> (传输层协议:流式协议)  ;0 -> :表示使用Tcpif(lfd == -1) {perror("socket");              return -1;}   // 2.设置端口复用int opt = 1;int ret =  setsockopt(lfd,SOL_SOCKET,SO_REUSEADDR,&opt,sizeof(opt)); if(ret == -1) {perror("setsockopt");return -1;}// 3.绑定struct sockaddr_in addr;addr.sin_family = AF_INET;addr.sin_port = htons(port);// 主机字节序(小端)转成网络字节序(大端) 端口的最大数量:2^16=65536addr.sin_addr.s_addr = INADDR_ANY;// 0.0.0.0 ret = bind(lfd,(struct sockaddr*)&addr,sizeof(addr));if(ret == -1) {perror("bind");return -1;}// 4.设置监听ret = listen(lfd,128);if(ret == -1) {perror("listen");return -1;}listener->lfd = lfd;listener->port = port;return listener;
}

(2)创建并初始化TcpServer实例

TcpServer结构与工作原理 

(一)服务器结构

  1. Listener: 监听特定端口,等待客户端的连接请求。主要包括端口和监听的文件描述符
  2. MainEventLoop主线程事件循环(主线程反应堆): 负责接收和处理来自客户端的请求
  3. ThreadPool线程池: 用于处理并发连接每个新连接都会有一个子线程处理
  4. TcpConnection: 每个客户端连接都会有一个对应的TcpConnection实例,用于处理该连接的通信

(二)初始化步骤

(1)创建服务器实例:申请TcpServer结构体的内存空间

(2)初始化Listener:

  • 指定服务器要绑定的本地端口(unsigned short类型)
  • 初始化监听的文件描述符

(3)初始化MainEventLoop主线程的事件循环或反应堆

(4)ThreadPool线程池初始化:根据需要的子线程数量(threadNum)初始化线程池

(5)返回值: 返回初始化完成的TcpServer的地址给调用者

// 初始化
struct TcpServer* tcpServerInit(unsigned short port,int threadNum);
// 初始化
struct TcpServer* tcpServerInit(unsigned short port,int threadNum) {struct TcpServer* tcp = (struct TcpServer*)malloc(sizeof(struct TcpServer));tcp->listener = listenerInit(port); // 创建listenertcp->mainLoop = eventLoopInit(); // 主线程的事件循环(反应堆模型)tcp->threadPool = threadPoolInit(tcp->mainLoop,threadNum); // 创建线程池tcp->threadNum = threadNum; // 线程数量return tcp;
}

二、启动TcpServer

// 启动服务器(不停检测有无客户端连接)
void tcpServerRun(struct TcpServer* server);
// 启动服务器(不停检测有无客户端连接)
void tcpServerRun(struct TcpServer* server) {// 启动线程池threadPoolRun(server->threadPool);// 初始化一个channel实例struct Channel* channel = channelInit(server->listener->lfd,ReadEvent,acceptConnection,NULL,server);// 添加检测的任务 eventLoopAddTask(server->mainLoop,channel,ADD);// 启动反应堆模型eventLoopRun(server->mainLoop);
}

>>启动服务器(不停检测有无客户端连接)

启动线程池,之后,需要让它处理任务,对于当前的TcpServer来说,是有任务可以处理的。在当前服务器启动之后,需要处理的文件描述符有且只有一个,就是用于监听的文件描述符,因此需要把待检测的文件描述符(用于监听的)添加到(mainLoop)事件循环里边。接着初始化一个channel实例,可调用eventLoopAddTask函数实现添加任务到任务队列。

  • 回顾channelInit函数:Channel模块的封装主要包括文件描述符、事件检测和回调函数。在服务器端,Channel主要用于封装文件描述符,用于监听和通信。事件检测是基于IO多路模型的,当文件描述符对应的事件被触发时,会调用相应的事件处理函数。在Channel结构中,需要指定读事件和写事件对应的回调函数。此外,还有一个data参数用于传递动态数据。
// 定义函数指针
typedef int(*handleFunc)(void* arg);// 定义文件描述符的读写事件
enum FDEvent {TimeOut = 0x01;ReadEvent = 0x02;WriteEvent = 0x04;
};struct Channel {// 文件描述符int fd;// 事件int events;// 回调函数handleFunc readCallback;// 读回调handleFunc writeCallback;// 写回调// 回调函数的参数void* arg;
};// 初始化一个Channel 
struct Channel* channelInit(int fd, int events, handleFunc readFunc, handleFunc writeFunc, void* arg);

 tcpServerRun函数中使用channelInit函数,这个channel实例主要用于封装监听文件描述符(lfd),用于监听。当lfd对应的事件被触发时,会调用相应的事件处理函数。其中它的读事件的回调函数acceptConnection函数:

// 初始化一个channel实例
struct Channel* channel = channelInit(server->listener->lfd,ReadEvent,acceptConnection,NULL,server);
int acceptConnection(void* arg) {struct TcpServer* server = (struct TcpServer*)arg;// 和客户端建立连接int cfd = accept(server->listener->lfd,NULL,NULL);if(cfd == -1) {perror("accept");return -1;}// 从线程池中去取出一个子线程的反应堆实例,去处理这个cfdstruct EventLoop* evLoop = takeWorkerEventLoop(server->mainLoop);// 将cfd放到 TcpConnection中处理tcpConnectionInit(cfd, evLoop);// ...(未完,待补充)return 0;
}
  • 回顾eventLoopAddTask函数:如果把channel放到了mainLoop的任务队列里边,任务队列在处理的时候需要知道对这个节点做什么操作,是添加到检测集合里去,还是从检测集合里删除,还是修改检测集合里的文件描述符的事件。那么对于监听的文件描述符,当然就是添加(ADD
// 添加任务到任务队列
int eventLoopAddTask(struct EventLoop* evLoop,struct Channel* channel,int type);

还有启动反应堆模型

// 启动反应堆模型
eventLoopRun(server->mainLoop);

>>TCP服务器初始化与线程池、事件循环的启动

知识点1:线程池的创建与启动:在初始化TcpServer时,线程池随之被创建。 启动线程池的函数是threadPoolRun函数

知识点2:事件循环的启动与任务添加:服务器启动后,需要将监听的文件描述符添加到事件循环(mainLoop反应堆)中。 添加任务的函数是eventLoopAddTask函数

知识点3:Channel的初始化与使用:获取channel实例需要调用初始化函数channelInit函数。 当读事件触发时,表示有新的客户端连接到达,需要与其建立连接。

 

相关文章:

基于多反应堆的高并发服务器【C/C++/Reactor】(中)创建并初始化TcpServer实例 以及 启动

对于一个TcpServer来说,它的灵魂是什么?就是需要提供一个事件循环EventLop(EventLoop),不停地去检测有没有客户端的连接到达,有没有客户端给服务器发送数据,描述的这些动作,反应堆模型能够胜任。当服务器和…...

边缘计算设备是什么意思。

问题描述:边缘计算设备是什么意思。 问题解答: 边缘计算(Edge Computing)是一种计算模型,其主要思想是在距离数据产生源头更近的地方进行数据处理和计算,而不是将所有数据传输到远程云服务器进行处理。边…...

使用ChatGPT midjourney 等AI智能工具,能为视觉营销做些什么?

使用ChatGPT、Midjourney等AI智能工具,可以极大地提升视觉营销的效率和创意水平。以下是这些工具在视觉营销中的一些具体应用: 内容创作与文案撰写(ChatGPT) 广告文案生成:根据产品特点和目标受众,生成吸…...

图像分割实战-系列教程4:unet医学细胞分割实战2(医学数据集、图像分割、语义分割、unet网络、代码逐行解读)

🍁🍁🍁图像分割实战-系列教程 总目录 有任何问题欢迎在下面留言 本篇文章的代码运行界面均在Pycharm中进行 本篇文章配套的代码资源已经上传 unet医学细胞分割实战1 unet医学细胞分割实战2 unet医学细胞分割实战3 unet医学细胞分割实战4 unet…...

防火墙未开端口导致zookeeper集群异常,kafka起不来

转载说明:如果您喜欢这篇文章并打算转载它,请私信作者取得授权。感谢您喜爱本文,请文明转载,谢谢。 问题描述: 主机信息: IPhostname10.0.0.10host1010.0.0.12host1210.0.0.13host13 在这三台主机上部署…...

React-hook-form-mui(二):表单数据处理

前言 在上一篇文章中,我们介绍了react-hook-form-mui的基础用法。本文将着表单数据处理。 react-hook-form-mui提供了丰富的表单数据处理功能,可以通过watch属性来获取表单数据。 Demo 下面是一个使用watch属性的例子: import React from…...

java网络文件地址url的转换为MultipartFile文件流

废话不多说,直接上代码 一、异常捕捉类 public class BusinessException extends RuntimeException {public BusinessException(String msg){super(msg);} }二、转换类 package com.example.answer_system.utils;import org.springframework.mock.web.MockMultipa…...

JS实现/封装节流函数

封装节流函数 节流原理:在一定时间内,只能触发一次 let timer, flag; /*** 节流原理:在一定时间内,只能触发一次* * param {Function} func 要执行的回调函数 * param {Number} wait 延时的时间* param {Boolean} immediate 是否立…...

ENVI 各版本安装指南

ENVI下载链接 https://pan.baidu.com/s/1APpjHHSsrXMaCcJUQGmFBA?pwd0531 1.鼠标右击【ENVI 5.6(64bit)】压缩包(win11及以上系统需先点击“显示更多选项”)选择【解压到 ENVI 5.6(64bit)】。 2.打开解压后的文件夹&#xff0c…...

60天零基础干翻C++————初识C++

初识c 命名空间命名空间的定义命名空间的使用 输入输出流缺省参数引用引用定义常量的引用引用的使用场景做函数参数引用做返回值 命名空间 命名空间的定义 在c语言中会有下面问题 上述代码中,全局变量rand 可能会命名冲突,如下图 此时编译失败&…...

考研复试英语口语问答举例第二弹

考研复试英语口语问答举例第二弹 文章目录 考研复试英语口语问答举例第二弹Question :介绍你的读研兴趣与动机Answer11:(自动化控制方向)Answer12:(集成电路方向)Answer13:&#xff…...

MyBatis-Plus实现自定义SQL语句的分页查询

正常开发的时候,有时候要写一个多表查询,然后多表查询之后还需要分页,MyBatis-Plus的分页插件功能挺不错的,可以很简单实现自定义SQL的分页查询。 分页插件配置 import com.baomidou.mybatisplus.annotation.DbType; import com…...

vue3 里的 ts 类型工具函数

目录 前言一、PropType\<T>二、MaybeRef\<T>三、MaybeRefOrGetter\<T>四、ExtractPropTypes\<T>五、ExtractPublicPropTypes\<T>六、ComponentCustomProperties七、ComponentCustomOptions八、ComponentCustomProps九、CSSProperties 前言 相关 …...

【SpringCloud】之远程消费(进阶使用)

&#x1f389;&#x1f389;欢迎来到我的CSDN主页&#xff01;&#x1f389;&#x1f389; &#x1f3c5;我是君易--鑨&#xff0c;一个在CSDN分享笔记的博主。&#x1f4da;&#x1f4da; &#x1f31f;推荐给大家我的博客专栏《SpringCloud开发之远程消费》。&#x1f3af;&a…...

自然语言处理24-T5模型的介绍与训练过程,利用简单构造数据训练微调该模型,体验整个过程

大家好,我是微学AI,今天给大家介绍一下自然语言处理24-T5模型的介绍与训练过程,利用简单构造数据训练微调该模型,体验整个过程。在大模型ChatGPT发布之前,NLP领域是BERT,T5模型为主导,T5(Text-to-Text Transfer Transformer)是一种由Google Brain团队在2019年提出的自然…...

CISSP 第5章 保护资产的安全

1、资产识别和分类 1.1 敏感数据 1.1.1 定义 敏感数据是任何非公开或非机密的信息&#xff0c;包括机密的、专有的、受保护的或因其对组织的价值或按照现有的法律和法规而需要组织保护的任何其他类型的数据。 1.1.2 个人身份信息PII 个人身份信息&#xff08;PII&#xff09…...

docker安装-在linux下的安装步骤

#切换到root用户 su yum安装jcc相关 yum -y install gcc yum -y install gcc-c 安装yum-utils sudo yum install -y yum-utils 设置stable镜像仓库 sudo yum-config-manager --add-repo https://mirrors.aliyun.com/docker-ce/linux/centos/docker-ce.repo 更新yum软件包索…...

在Uniapp中使用Echarts创建可视化图表

在uniapp中可以引入echarts创建数据可视化图表。 1. 安装Echarts 使用npm安装echarts插件&#xff0c;命令如下&#xff1a; npm install echarts --save2. 引入Eharts 在需要使用Echarts的页面引入&#xff1a; import *as echarts from echarts3. 创建实例 创建画布元素…...

基于python的leetcode算法介绍之动态规划

文章目录 零 算法介绍一 例题介绍 使用最小花费爬楼梯问题分析 Leetcode例题与思路[118. 杨辉三角](https://leetcode.cn/problems/pascals-triangle/)解题思路题解 [53. 最大子数组和](https://leetcode.cn/problems/maximum-subarray/)解题思路题解 [96. 不同的二叉搜索树](h…...

通信原理期末复习——计算大题(一)

个人名片&#xff1a; &#x1f981;作者简介&#xff1a;一名喜欢分享和记录学习的在校大学生 &#x1f42f;个人主页&#xff1a;妄北y &#x1f427;个人QQ&#xff1a;2061314755 &#x1f43b;个人邮箱&#xff1a;2061314755qq.com &#x1f989;个人WeChat&#xff1a;V…...

【萤火虫系列教程】2/5-Adobe Firefly 文字​生成​图像

文字​生成​图像 登录账号后&#xff0c;在主页点击文字生成图像的【生成】按钮&#xff0c;进入到文字生成图像 查看图像 在文字生成图像页面&#xff0c;可以看到别人生成的图像。 点击某个图像&#xff0c;就可以进入图像详情&#xff0c;可以看到文字描述。 生成图像 我…...

JDK 11:崭新特性解析

JDK 11&#xff1a;崭新特性解析 JDK 11&#xff1a;崭新特性解析1. HTTP Client&#xff08;标准化&#xff09;示例代码 2. 局部变量类型推断的扩展示例代码 3. 新的字符串方法示例代码 4. 动态类文件常量示例代码 5. Epsilon 垃圾收集器使用方式 结语 JDK 11&#xff1a;崭新…...

leetcode.在链表中插入最大公约数

文章目录 题目解题方法复杂度Code Problem: 2807. 在链表中插入最大公约数 题目 给你一个链表的头 head &#xff0c;每个结点包含一个整数值。 在相邻结点之间&#xff0c;请你插入一个新的结点&#xff0c;结点值为这两个相邻结点值的 最大公约数 。 请你返回插入之后的链表。…...

云原生学习系列之基础环境准备(单节点安装kubernetes)

一、环境要求 操作系统CentOS 7.x-86_x64 硬件配置&#xff1a;内存2GB或2G&#xff0c;CPU 2核或CPU 2核&#xff0c;需要在虚拟机中提前设置好&#xff0c;不然后续会报错 二、系统初始化 1、设置主机名 # 在master节点执行 hostnamectl set-hostname master01 2、配置主…...

【数据结构】二叉树的概念及堆

前言 我们已经学过了顺序表、链表、栈和队列这些属于线性结构的数据结构&#xff0c;那么下面我们就要学习我们第一个非线性结构&#xff0c;非线性结构又有哪些值得我们使用的呢&#xff1f;那么接下来我们就将谈谈树的概念了。 1.树的概念与结构 1.1树的概念 树是一种非线性…...

美年大健康黄伟:从选型到迁移,一个月升级核心数据库

核心生产系统的数据库&#xff0c;从接到替换需求到完成分布式升级&#xff0c;需要多久&#xff1f;一个月&#xff0c;这是美年大健康的回答。一个月集中调配各种资源&#xff0c;美年大健康完成了应用程序基本零改造的平滑迁移&#xff0c;新数据库在成本更低的前提下&#…...

OpenHarmony应用构建工具Hvigor的构建流程

前言 OpenHarmony 应用和服务使用 Hvigor 作为工程的构建工具。本篇文章将介绍 Hvigor 的构建流程&#xff0c;通过修改脚本配置使 Hvigor 执行自定义任务。 Hvigor 的构建流程 加载命令行参数和环境变量&#xff1b;初始化项目结构&#xff0c;创建 Project 和 Module 实例…...

ChatGPT在金融财务领域的10种应用方法

1.生成报告 在金融领域中&#xff0c;最耗时的任务之一是报告生成。通过ChatGPT&#xff0c;您可以在一定程度上自动化这个过程。这款人工智能工具可以获取关于公司财务表现的结构化数据&#xff0c;并生成一份书面摘要&#xff0c;详细说明关键点、趋势和观察结果。这个功能在…...

全程云OA ajax.ashx SQL注入漏洞复现

0x01 产品简介 全程云OA为企业提供日常办公管理、公文管理、工作请示、汇报、档案、知识体系、预算控制等26个功能,超过100多个子模块。为企业内部提供高效、畅通的信息渠道,同时也能大力推动公司信息系统发展,提高企业的办公自动化程度和综合管理水平,加快企业信息的流通…...

VMware 安装 macOS虚拟机(附工具包)

VMware 安装 macOS虚拟机&#xff0c;在Windows上体验苹果macOS系统&#xff01; 安装教程&#xff1a;VMware 安装 macOS虚拟机VMware Workstation Pro 是一款强大的虚拟机软件&#xff0c;可让您在 Windows 电脑上运行 macOS 系统。只需简单几步操作&#xff0c;即可轻松安装…...

网站搭建课程标准/谷歌浏览器手机版

试题 算法提高 成绩排名资源限制时间限制&#xff1a;1.0s 内存限制&#xff1a;256.0MB问题描述小明刚经过了一次数学考试&#xff0c;老师由于忙碌忘记排名了&#xff0c;于是老师把这个光荣的任务交给了小明&#xff0c;小明则找到了聪明的你&#xff0c;希望你能帮他解决这…...

wordpress开发视频教程/北京网站建设公司报价

一、发展现状 1、教育经费 随着我国经济迅速发展&#xff0c;社会对国民教育的重视程度日益增长&#xff0c;但在教育经费持续增加投人的同时&#xff0c;需重点关注教育经费的合法合规&#xff0c;真正做到效益的产出。只有建立完善的教育经费管理体系&#xff0c;坚持财务信息…...

网页制作的方法/整站优化seo平台

可以通过下面的指令查询&#xff1a; deno info...

yii2 网站开发/软件推广平台

《计算机导论》教学大纲一、课程概述1. 课程研究对象和研究内容计算机导论对计算机科学的核心内容作概括介绍&#xff1b;使学生深刻理解计算机系统的信息处理功能本质&#xff1b;掌握数据表达和数据加工表达的层次方法&#xff1b;了解计算机系统的功能组成&#xff1b;认识计…...

本科自考助学班/青岛seo计费

今天&#xff0c;移动支付领域迈出了新的一步&#xff1a;万事达卡和德国电信宣布&#xff0c;二者将携手沿着德国电信的业务足迹在欧洲推出移动支付&#xff0c;今年第三季度将在波兰推出NFC钱包解决方案&#xff0c;不久之后再推广到德国。不过目前美国市场还不在考虑范围内。…...

商城网站怎么做的/seo营销怎么做

大型宾馆无线解决方案疑问 回复&#xff1a;7 阅读&#xff1a;2782009-08-23 11:49:53 情况如下&#xff1a;一个宾馆有五栋楼&#xff0c;已经装修好&#xff01;有会议室&#xff0c;茶艺&#xff0c;客房&#xff0c;餐饮大楼&#xff0c;基本上齐全&#xff01;大约有5…...