Redis的实现二: c、c++的网络通信编程技术,让服务器处理多个client
看过上期的都知道,我是搞java的,所以对这些可能理解不是很清楚,各位看完可以尽情发言。
事件循环和非阻塞IO
在服务器端网络编程中,有三种处理并发连接的方法。
它们是:分叉、多线程和事件循环。分叉为每个客户端连接创建新进程,以实现并发性。多线程使用线程而不是进程。事件循环使用轮询和非阻塞IO,通常在单个线程上运行。由于进程和线程的开销,大多数现代生产级软件使用事件循环进行网络连接。
我们服务器的事件循环的简化伪代码是:
all_fds = [...]
while True:active_fds = poll(all_fds)
for each fd in active_fds:do_something_with(fd)
def do_something_with(fd):if fd is a listening socket:add_new_client(fd)elif fd is a client connection:while work_not_done(fd):do_something_to_client(fd)def do_something_to_client(fd):if should_read_from(fd):data = read_until_EAGAIN(fd)process_incoming_data(data)while should_write_to(fd):write_until_EAGAIN(fd)
if should_close(fd):destroy_client(fd)
all_fds
是一个包含所有需要监控的文件描述符的列表。while True:
是一个无限循环,它会一直运行,直到程序被外部中断。active_fds = poll(all_fds)
调用poll函数,返回一个包含所有准备好进行I/O操作的文件描述符的列表。for each fd in active_fds:
遍历这个列表,对每个文件描述符执行相应的操作。do_something_with(fd)
是一个函数,根据文件描述符的类型执行相应的操作。def do_something_with(fd):
定义了这个函数。if fd is a listening socket:
如果文件描述符是一个监听套接字,那么调用add_new_client(fd)
函数添加新的客户端连接。elif fd is a client connection:
如果文件描述符是一个客户端连接,那么进入一个循环,直到工作完成为止。在这个循环中,调用do_something_to_client(fd)
函数处理客户端的数据。def do_something_to_client(fd):
定义了这个函数。if should_read_from(fd):
如果应该从文件描述符读取数据,那么调用read_until_EAGAIN(fd)
函数读取数据,然后调用process_incoming_data(data)
函数处理数据。while should_write_to(fd):
如果应该向文件描述符写入数据,那么调用write_until_EAGAIN(fd)
函数写入数据。if should_close(fd):
如果应该关闭文件描述符,那么调用destroy_client(fd)
函数销毁客户端连接。
我们不只是对fd做一些事情(读、写或接受),而是使用轮询操作来告诉我们哪些fd可以立即操作而不阻塞。当我们在fd上执行IO操作时,该操作应该在非阻塞模式下执行。
epoll的使用
在Linux上,除了poll系统调用,还有select和epoll。古老的select系统调用基本上与轮询相同,只是最大fd数被限制为一个小数目,这使得它在现代应用程序中已经过时了。epoll API由3个系统调用组成:epoll_create、epoll_wait和epoll_ctl。epoll API是有状态的,而不是提供一组fd作为系统调用参数,epoll_ctl用于操作由epoll_create创建的fd集,epoll_wait正在对其进行操作。
epoll API执行与poll()类似的任务:监视多个文件描述符,以查看其中任何一个文件是否可以进行I/O操作。epoll API可以用作边缘触发或水平触发接口,并且可以很好地扩展到大量监视的文件描述符。以下提供系统调用来创建和管理epoll实例:
epoll_create()创建一个epoll实例并返回一个引用该实例的文件描述符。
然后通过epoll_ctl()注册对特定文件描述符的兴趣。当前在epoll上注册的文件描述符集,实例有时称为epoll集。
epoll_wait()等待I/O事件,如果当前没有事件可用,则阻塞调用线程。
#define MAX_EVENTS 10struct epoll_event ev, events[MAX_EVENTS];int listen_sock, conn_sock, nfds, epollfd;/* Set up listening socket, 'listen_sock' (socket(),bind(), listen()) */epollfd = epoll_create(10);if (epollfd == -1) {perror("epoll_create");exit(EXIT_FAILURE);}ev.events = EPOLLIN;ev.data.fd = listen_sock;if (epoll_ctl(epollfd, EPOLL_CTL_ADD, listen_sock, &ev) == -1) {perror("epoll_ctl: listen_sock");exit(EXIT_FAILURE);}for (;;) {nfds = epoll_wait(epollfd, events, MAX_EVENTS, -1);if (nfds == -1) {perror("epoll_pwait");exit(EXIT_FAILURE);}for (n = 0; n < nfds; ++n) {if (events[n].data.fd == listen_sock) {conn_sock = accept(listen_sock,(struct sockaddr *) &local, &addrlen);if (conn_sock == -1) {perror("accept");exit(EXIT_FAILURE);}setnonblocking(conn_sock);ev.events = EPOLLIN | EPOLLET;ev.data.fd = conn_sock;if (epoll_ctl(epollfd, EPOLL_CTL_ADD, conn_sock,&ev) == -1) {perror("epoll_ctl: conn_sock");exit(EXIT_FAILURE);}} else {do_use_fd(events[n].data.fd);}}}
这段代码的主要功能是创建一个监听套接字,并使用epoll机制来处理客户端连接请求。以下是代码的详细解析:
#define MAX_EVENTS 10
:定义了一个宏常量MAX_EVENTS
,表示最多可以处理的事件数量为10。struct epoll_event ev, events[MAX_EVENTS];
:定义了一个结构体数组events
,用于存储epoll事件。每个事件由一个epoll_event
结构体表示。int listen_sock, conn_sock, nfds, epollfd;
:定义了四个整型变量,分别表示监听套接字、新连接的套接字、返回的文件描述符数量和epoll实例的文件描述符。epollfd = epoll_create(10);
:创建了一个epoll实例,最大文件描述符数量为10。如果创建失败,将打印错误信息并退出程序。ev.events = EPOLLIN;
:设置事件类型为可读事件(EPOLLIN)。ev.data.fd = listen_sock;
:将监听套接字的文件描述符设置为事件的关联数据。if (epoll_ctl(epollfd, EPOLL_CTL_ADD, listen_sock, &ev) == -1)
:将监听套接字添加到epoll实例中,以便接收新的连接请求。如果添加失败,将打印错误信息并退出程序。for (;;)
:无限循环,不断处理事件。nfds = epoll_wait(epollfd, events, MAX_EVENTS, -1);
:调用epoll_wait
函数等待事件发生。参数-1
表示等待所有类型的事件。返回值表示实际发生的事件数量。如果发生错误,将打印错误信息并退出程序。for (n = 0; n < nfds; ++n)
:遍历所有发生的事件。if (events[n].data.fd == listen_sock)
:判断事件是否与监听套接字相关联。如果是,表示有新的连接请求。conn_sock = accept(listen_sock, (struct sockaddr *) &local, &addrlen);
:接受新的连接请求,并将新连接的套接字赋值给conn_sock
。如果接受失败,将打印错误信息并退出程序。setnonblocking(conn_sock);
:将新连接的套接字设置为非阻塞模式,以便后续处理。ev.events = EPOLLIN | EPOLLET;
:设置事件类型为可读事件(EPOLLIN),并启用边缘触发(EPOLLET)。ev.data.fd = conn_sock;
:将新连接的套接字的文件描述符设置为事件的关联数据。if (epoll_ctl(epollfd, EPOLL_CTL_ADD, conn_sock, &ev) == -1)
:将新连接的套接字添加到epoll实例中,以便后续处理。如果添加失败,将打印错误信息并退出程序。else
:如果事件与监听套接字无关,表示是一个已连接的客户端发送的数据。调用do_use_fd
函数进行处理。
相关文章:
Redis的实现二: c、c++的网络通信编程技术,让服务器处理多个client
看过上期的都知道,我是搞java的,所以对这些可能理解不是很清楚,各位看完可以尽情发言。 事件循环和非阻塞IO 在服务器端网络编程中,有三种处理并发连接的方法。 它们是:分叉、多线程和事件循环。分叉为每个客户端连接创建新…...

QT上位机开发(动画效果)
【 声明:版权所有,欢迎转载,请勿用于商业用途。 联系信箱:feixiaoxing 163.com】 不管是仿真,还是对真实环境的一比一模拟,动画都是非常好的一种呈现方式。目前在qt上面,实现动画主要有两种方法…...
手写实现 bind 函数
Function.prototype.myBind function(context) {if (typeof this ! function) {return}const args [...arguments].slice(1)const fn thisreturn function Fn() {// 判断函数作为构造函数的情况,这个时候需要传入当前的函数的this给apply调用,其余情况…...

安卓Android Studio读写MifareOne M1 IC卡源码
本示例使用的发卡器:https://item.taobao.com/item.htm?id615391857885&spma1z10.5-c-s.w4002-21818769070.11.3d2f789eOUPJBK <?xml version"1.0" encoding"utf-8"?> <androidx.constraintlayout.widget.ConstraintLayout xm…...

一二三应用开发平台文件处理设计与实现系列之5——MinIO技术预研
背景 上篇介绍了文件读写框架设计与实现,同时顺便说明了本地磁盘存储模式的实现模式。 今天来说下基于文件读写框架,如何集成对象存储组件minio,集成之前,需要对minio进行必要的了解,本篇是minio的技术预研。 minio简…...
Native.js是什么
Native.js 是一个开源项目,旨在通过 JavaScript 调用原生 Android API。它的目标是让 JavaScript 开发者能够使用 Android 原生 API,从而在不编写原生代码的情况下构建 Android 应用。 使用 Native.js,开发者可以使用 JavaScript 调用 Andro…...

Vant-ui图片懒加载
核心代码 在你的全局顶部引入和初始化 Vue.use(vant.Lazyload, {loading: /StaticFile/img/jiazai.jpg,error: /StaticFile/img/jiazai.jpg,lazyComponent: false, });//图片懒加载 <img v-lazy"https://img-blog.csdnimg.cn/direct/3d2c8a7e2c0040488a8128c3e381d58…...

创建EasyCodeMybatisCodeHelperPro模板文件用于将数据库表生成前端json文件
在intellij idea中,通过插件EasyCodeMybatisCodeHelperPro,从现有的模板文件中选择一个复制粘贴,然后稍为修改,即可得到一个合适的模板文件。 现在的前端,越来越像后端。TypeScript替代了JavaScript,引入了…...

华为端口安全常用3种方法配置案例
安全动态mac地址学习功能 [Huawei]int g0/0/01 interface GigabitEthernet0/0/1 port-security enable //开启安全 port-security max-mac-num 2 //最多为2个mac地址学习 port-security protect-action restrict //丢包带警告 port-security aging-time 1 //mac地址的老化时间…...

RH850P1X芯片学习笔记-Flash Memory
文章目录 FeaturesClock Supply Block DiagramFlash SizeMemory ConfigurationRegistersRegister Base AddressList of RegistersRegister Reset Condition 与Flash Memory相关的操作模式Functional OverviewOption BytesOPBT0 — Option Byte 0OPBT1 — Option Byte 1OPBT2 —…...

利用XSS漏洞打cookie
目录 1、为什么要打cookie? 2、怎样利用XSS来打cookie? 3、利用Bluelotus_xssReceiver平台来打cookie 4、利用beef-xss平台来打cookie 上一篇给大家介绍了xss漏洞的基础知识,在本篇章将会介绍和演示一下利用xss漏洞打cookie的演示&#x…...
用java写个redis工具类
下面是一个简单的Redis工具类的示例,使用Java语言编写: import redis.clients.jedis.Jedis;public class RedisUtils {private static Jedis jedis;public static void connect(String host, int port) {jedis new Jedis(host, port);}public static v…...
实现防抖函数
// 防抖就是,事件触发 delay 秒后再执行,如果有重新的触发,重新计时 function debounce(func, delay) {if(typeof func ! function) {return}let timer 0return function () {if (timer) {clearTimeout(timer)timer null}timer setTimeout…...
MetaGPT task1学习
基础知识学习了解: 安装环境: 获取MetaGPT 使用pip获取MetaGPT pip install -i https://pypi.tuna.tsinghua.edu.cn/simple metagpt0.5.2 配置MetaGPT 完成MetaGPT后,我们还需要完成一些配置才能开始使用这个强力的框架,包括配…...
关于量子计算机的设想
从CPU架构说起 CISCRISCNISCCCSC CISC是复杂指令集计算机,以x86为代表; RISC是精简指令集计算机,以ARM为代表; NISC是无指令集计算机,CCSC是核-电路分离计算机,这两个是本文要讨论的内容。 如果没有指令…...

序列模型(4)—— Scaling Laws
本文介绍 LLM 训练过程中重要的 Scaling Laws,这是一个经验规律,指出了固定训练成本(总计算量FLOPs) C C C 时,如何调配模型规模(参数量) N N N 和训练 Token 数据量 D D D,才能实现…...

【软件测试学习笔记1】测试基础
1.软件测试的定义 软件的定义:控制计算机硬件工作的工具 软件的基本组成:页面客户端,代码服务器,数据服务器 软件产生的过程:需求产生(产品经理),需求文档,设计效果图…...
pytorch详细探索各种cnn卷积神经网络
目录 torch.nn.functional子模块详解 conv1d 用法和用途 使用技巧 适用领域 参数 注意事项 示例代码 conv2d 用法和用途 使用技巧 适用领域 参数 注意事项 示例代码 conv3d 用法和用途 使用技巧 适用领域 参数 注意事项 示例代码 conv_transpose1d 用法…...

OpenCV——八邻域断点检测
目录 一、理论基础1、八邻域2、断点检测 二、代码实现三、结果展示四、参考链接 OpenCV——八邻域断点检测由CSDN点云侠原创,爬虫自重。如果你不是在点云侠的博客中看到该文章,那么此处便是不要脸的爬虫。 一、理论基础 1、八邻域 图1 八邻域示意图 图…...

leetcode238:除自身以外数组的乘积
文章目录 1.使用除法(违背题意)2.左右乘积列表3.空间复杂度为O(1)的方法 在leetcode上刷到了这一题,一开始并没有想到好的解题思路,写篇博客再来梳理一下吧。 题目要求: 不使用除法在O(n)时间复杂度内 1.使用除法&am…...

全球首个30米分辨率湿地数据集(2000—2022)
数据简介 今天我们分享的数据是全球30米分辨率湿地数据集,包含8种湿地亚类,该数据以0.5X0.5的瓦片存储,我们整理了所有属于中国的瓦片名称与其对应省份,方便大家研究使用。 该数据集作为全球首个30米分辨率、覆盖2000–2022年时间…...
macOS多出来了:Google云端硬盘、YouTube、表格、幻灯片、Gmail、Google文档等应用
文章目录 问题现象问题原因解决办法 问题现象 macOS启动台(Launchpad)多出来了:Google云端硬盘、YouTube、表格、幻灯片、Gmail、Google文档等应用。 问题原因 很明显,都是Google家的办公全家桶。这些应用并不是通过独立安装的…...
【算法训练营Day07】字符串part1
文章目录 反转字符串反转字符串II替换数字 反转字符串 题目链接:344. 反转字符串 双指针法,两个指针的元素直接调转即可 class Solution {public void reverseString(char[] s) {int head 0;int end s.length - 1;while(head < end) {char temp …...

Keil 中设置 STM32 Flash 和 RAM 地址详解
文章目录 Keil 中设置 STM32 Flash 和 RAM 地址详解一、Flash 和 RAM 配置界面(Target 选项卡)1. IROM1(用于配置 Flash)2. IRAM1(用于配置 RAM)二、链接器设置界面(Linker 选项卡)1. 勾选“Use Memory Layout from Target Dialog”2. 查看链接器参数(如果没有勾选上面…...
DeepSeek 技术赋能无人农场协同作业:用 AI 重构农田管理 “神经网”
目录 一、引言二、DeepSeek 技术大揭秘2.1 核心架构解析2.2 关键技术剖析 三、智能农业无人农场协同作业现状3.1 发展现状概述3.2 协同作业模式介绍 四、DeepSeek 的 “农场奇妙游”4.1 数据处理与分析4.2 作物生长监测与预测4.3 病虫害防治4.4 农机协同作业调度 五、实际案例大…...
在web-view 加载的本地及远程HTML中调用uniapp的API及网页和vue页面是如何通讯的?
uni-app 中 Web-view 与 Vue 页面的通讯机制详解 一、Web-view 简介 Web-view 是 uni-app 提供的一个重要组件,用于在原生应用中加载 HTML 页面: 支持加载本地 HTML 文件支持加载远程 HTML 页面实现 Web 与原生的双向通讯可用于嵌入第三方网页或 H5 应…...
Java毕业设计:WML信息查询与后端信息发布系统开发
JAVAWML信息查询与后端信息发布系统实现 一、系统概述 本系统基于Java和WML(无线标记语言)技术开发,实现了移动设备上的信息查询与后端信息发布功能。系统采用B/S架构,服务器端使用Java Servlet处理请求,数据库采用MySQL存储信息࿰…...
【SSH疑难排查】轻松解决新版OpenSSH连接旧服务器的“no matching...“系列算法协商失败问题
【SSH疑难排查】轻松解决新版OpenSSH连接旧服务器的"no matching..."系列算法协商失败问题 摘要: 近期,在使用较新版本的OpenSSH客户端连接老旧SSH服务器时,会遇到 "no matching key exchange method found", "n…...

MacOS下Homebrew国内镜像加速指南(2025最新国内镜像加速)
macos brew国内镜像加速方法 brew install 加速formula.jws.json下载慢加速 🍺 最新版brew安装慢到怀疑人生?别怕,教你轻松起飞! 最近Homebrew更新至最新版,每次执行 brew 命令时都会自动从官方地址 https://formulae.…...

第一篇:Liunx环境下搭建PaddlePaddle 3.0基础环境(Liunx Centos8.5安装Python3.10+pip3.10)
第一篇:Liunx环境下搭建PaddlePaddle 3.0基础环境(Liunx Centos8.5安装Python3.10pip3.10) 一:前言二:安装编译依赖二:安装Python3.10三:安装PIP3.10四:安装Paddlepaddle基础框架4.1…...