day38 tcp 并发 ,linux下的IO模型----IO多路复用
TCP 并发
由于tcp协议只能实现一对一的通信模式。为了实现一对多,有以下的的处理方式
1. 多进程
开销大
效率低
2. 多线程
创建线程需要耗时
3. 线程池
多线程模型创建线程耗时问题,提前创建
4. IO多路复用
在不创建进程和线程的前提下,对多个文件描述符进行同时监测
IO:fd读写, 共用一个进程
1.多进程(服务端)
#include<stdio.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <netinet/ip.h>
#include <arpa/inet.h>
#include <string.h>
#include <signal.h>
#include <sys/wait.h>
#include <unistd.h>int init_tpc_ser(const char *ip , unsigned short port)
{int sockfd = socket(AF_INET, SOCK_STREAM, 0);if(sockfd < 0){perror("fail socket");return -1;}struct sockaddr_in ser;ser.sin_family = AF_INET;ser.sin_port = htons(port);ser.sin_addr.s_addr = inet_addr(ip);int ret = bind(sockfd,(struct sockaddr *)&ser,sizeof(ser));if(ret < 0){perror("fail bind ");return -1;}return sockfd;}void handler(int signo)
{wait(NULL);
}int main(int agrc, char *agrv[])
{signal (17,handler);int sockfd = init_tpc_ser("192.168.0.179",50000);int ret = listen (sockfd,100);char buff[1024] = {0};if(ret < 0){perror("fail listen");return -1;}while(1){int connfd = accept(sockfd,NULL,NULL);if(connfd < 0){perror("fail accept");return -1;}pid_t pid = fork();if(pid > 0){}else if(pid == 0){while(1){memset(buff, 0 ,sizeof(buff));int ret = recv(connfd,buff ,sizeof(buff),0);printf("%s\n",buff);if(ret <= 0){return -1;}strcat(buff,"-----ok");ret = send(connfd, buff,sizeof(buff),0);if(ret < 0){return -1;} }return 0;}else{printf("fork fail");return -1;}}close(sockfd);return-1;}
2.多线程(服务端)
#include<stdio.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <netinet/ip.h>
#include <arpa/inet.h>
#include <string.h>
#include <signal.h>
#include <sys/wait.h>
#include <unistd.h>
#include <pthread.h>int init_tpc_ser(const char *ip , unsigned short port)
{int sockfd = socket(AF_INET, SOCK_STREAM, 0);if(sockfd < 0){perror("fail socket");return -1;}struct sockaddr_in ser;ser.sin_family = AF_INET;ser.sin_port = htons(port);ser.sin_addr.s_addr = inet_addr(ip);int ret = bind(sockfd,(struct sockaddr *)&ser,sizeof(ser));if(ret < 0){perror("fail bind ");return -1;}return sockfd;}char buff[1024] = {0};
void* task(void *reg)
{int connfd = *(int *)reg;//传过来保存就不会收到其他线程影响while(1){memset(buff, 0 ,sizeof(buff));int ret = recv(connfd,buff ,sizeof(buff),0);printf("%s\n",buff);if(ret == 0){break;}strcat(buff,"-----ok");ret = send(connfd, buff,sizeof(buff),0);if(ret = 0){break;} }close(connfd);pthread_detach(pthread_self());//设置线程分离属性。主线程无暇回收次线程return 0;
}int main(int agrc, char *agrv[])
{int sockfd = init_tpc_ser("192.168.0.179",50000);int ret = listen (sockfd,100);int connfd = 0;pthread_t tid = 0;if(ret < 0){perror("fail listen");return -1;}while(1){connfd = accept(sockfd,NULL,NULL);if(connfd < 0){perror("fail accept");return -1;}pthread_create(&tid,NULL,task,&connfd); }close(sockfd);return-1;}
3.io多路复用(具体见下)
2.IO模型
Linux下常用的IO模型:
1. 阻塞IO
fgets
read
getchar
fread
fgetc
recv
recvfrom
1. 让多个IO事件以同步方式处理(顺序处理),
2. 多个IO事件之间互相影响
3. CPU占有率低
2. 非阻塞IO
将IO对应的文件描述符设置成非阻塞方式。O_NONBLOCKfcntl1.非阻塞一般搭配轮询方式同时监测多个IO2.cpu占有率高
#include "head.h"int main(int argc, const char *argv[])
{mkfifo("./fifo", 0664); char buff[1024] = {0};int fifofd = open("./fifo", O_RDONLY);if (fifofd < 0){perror("fail open fifo");return -1;}//1, 获取文件描述符(终端)原flags特性int flags = fcntl(0, F_GETFL);//2. 给原flags增加非阻塞特性flags = flags | O_NONBLOCK;//3. 给文件描述符设置新flags特性fcntl(0, F_SETFL, flags);while (1){memset(buff, 0, sizeof(buff));fgets(buff, sizeof(buff), stdin);//不会堵塞在这里,内核检测到键盘输入自动运行printf("STDIN : %s\n", buff);memset(buff, 0, sizeof(buff));read(fifofd, buff, sizeof(buff));printf("FIFO : %s\n", buff);}close(fifofd);return 0;
}
3. 信号驱动IO
SIGIO1.实现异步IO操作,节省CPU开销2.只能针对比较少的IO事件(信号很少)
#include "head.h"char buff[1024] = {0};
void handler (int signo)
{memset(buff, 0, sizeof(buff));fgets(buff, sizeof(buff), stdin);printf("STDIN : %s\n", buff);}
int main(int argc, const char *argv[])
{signal(SIGIO,handler);mkfifo("./fifo", 0664); int fifofd = open("./fifo", O_RDONLY);if (fifofd < 0){perror("fail open fifo");return -1;}//1, 获取文件描述符原flags特性int flags = fcntl(0, F_GETFL);//2. 给原flag异步flags = flags |O_ASYNC;//3. 给文件描述符设置新flags特性fcntl(0, F_SETFL, flags);//关联信号与当前进程fcntl(0,F_SETOWN,getpid());while (1){memset(buff, 0, sizeof(buff));read(fifofd, buff, sizeof(buff));printf("FIFO : %s\n", buff);}close(fifofd);return 0;
}
4. IO多路复用(IO多路转接)
在不创建新的进程和线程的前提下, 在一个进程中,同时监测多个IO
1. select1. 文件描述符集合以数组(位图)的方式保存,最多监测1024个文件描述符。2. 文件描述符集合创建在应用层,需要应用层和内核层反复拷贝3. 内核层返回整个文件描述符集合,需要用户层遍历查找到达事件的文件描述符4. 只能工作在水平触发模式(低速模式)
2. poll1. 文件描述符集合以链表的方式保存,监测文件描述符可超过1024。2. 文件描述符集合创建在应用层,需要应用层和内核层反复拷贝3. 内核层返回整个文件描述符集合,需要用户层遍历查找到达事件的文件描述符4. 只能工作在水平触发模式(低速模式)
3. epoll 1. 文件描述符集合以树型结构(红黑树)保存,监测文件描述符可超过1024, 提高了数据的查找速度。2. 文件描述符集合创建在内核层;3. 返回的是到达事件的文件描述符集合,无需遍历查找4. 可以工作在水平触发模式(低速模式),也可以工作在边沿触发模式(高速模式)
1.select
- 创建文件描述符集合
2. 添加关注的文件描述符到集合
3. 传递给内核,内核开始监测IO事件 select
4. IO事件到达则返回结果–》
2.哪个fd事件到达执行哪个
int select(int nfds, fd_set *readfds, fd_set *writefds,fd_set *exceptfds, struct timeval *timeout);
功能:通知内核监测IO事件并返回事件结果
参数:nfds:最大文件描述符+1readfds: 文件描述符读事件集合writefds:文件描述符写事件集合exceptfds:其他timeout : 超时时间
返回值:成功:返回达到的事件的个数失败:-1设置超时:超时时间到,但没有事件到达:0void FD_CLR(int fd, fd_set *set);int FD_ISSET(int fd, fd_set *set);void FD_SET(int fd, fd_set *set);void FD_ZERO(fd_set *set);
#include "head.h"int main(int argc, const char *argv[])
{mkfifo("./fifo", 0664); char buff[1024] = {0};int fifofd = open("./fifo", O_RDONLY);if (fifofd < 0){perror("fail open fifo");return -1;}int maxfd = 0;fd_set rdfds;//创建集合FD_ZERO(&rdfds);//清0//加入集合FD_SET(0,&rdfds);FD_SET(fifofd,&rdfds);maxfd = fifofd >maxfd ?fifofd:maxfd;fd_set rdfdscopy;while(1){rdfdscopy= rdfds;//防止rdfds被修改,//发送位图给内核int cnt = select(maxfd+1,&rdfdscopy,NULL,NULL,NULL);if(cnt < 0){perror("fail select");return -1;}//判断是否事件到达if(FD_ISSET(0,&rdfdscopy)){memset(buff,0,sizeof(buff));fgets(buff,sizeof(buff),stdin);printf("stdin : %s",buff);}if(FD_ISSET(fifofd,&rdfdscopy)){memset(buff,0,sizeof(buff));read(fifofd,buff,sizeof(buff));printf("fifo : %s\n",buff);}}close(fifofd);return 0;
}
select实现并发tcp
#include "head.h"int init_tcp_ser(const char *ip, unsigned short port)
{int sockfd = socket(AF_INET, SOCK_STREAM, 0);if (sockfd < 0){perror("fail socket");return -1;}struct sockaddr_in ser;ser.sin_family = AF_INET;ser.sin_port = htons(port);ser.sin_addr.s_addr = inet_addr(ip);int ret = bind(sockfd, (struct sockaddr *)&ser, sizeof(ser));if (ret < 0){perror("fail bind");return -1;}ret = listen(sockfd, 100);if (ret < 0){perror("fail listen");return -1;}return sockfd;
} int main(int argc, const char *argv[])
{char buff[1024] = {0};int sockfd = init_tcp_ser("192.168.0.166", 50000); if (sockfd < 0){return -1;}struct sockaddr_in cli;socklen_t clilen = sizeof(cli);int maxfd = 0;//1、 创建文件描述符集合fd_set rdfds, rdfdstmp;FD_ZERO(&rdfds);//2. 将关注的监听套接字加入到集合FD_SET(sockfd, &rdfds);maxfd = sockfd;while (1){//3. 内核开始检测套接字事件rdfdstmp = rdfds;int cnt = select(maxfd+1, &rdfdstmp, NULL, NULL, NULL);if (cnt < 0){perror("fail select");return -1;}// 是否有监听套接字事件到达if (FD_ISSET(sockfd, &rdfdstmp)){int connfd = accept(sockfd, (struct sockaddr *)&cli, &clilen);if (connfd < 0){perror("fail accept");return -1;}printf("[%s : %d] get online!\n", inet_ntoa(cli.sin_addr), ntohs(cli.sin_port));FD_SET(connfd, &rdfds);maxfd = maxfd > connfd ? maxfd : connfd;}//循环遍历剩余套接字,是否有通讯套接字事件到达for (int i = sockfd+1; i <= maxfd; i++){if (FD_ISSET(i, &rdfdstmp)){memset(buff, 0, sizeof(buff));ssize_t size = recv(i, buff, sizeof(buff), 0);if (size < 0){perror("fail recv");FD_CLR(i, &rdfds);close(i);continue;}else if (0 == size){FD_CLR(i, &rdfds);close(i);continue;}printf("%s\n", buff);strcat(buff, "-----ok!");size = send(i, buff, strlen(buff), 0);if (size < 0){perror("fail recv");FD_CLR(i, &rdfds);close(i);continue; }}}}close(sockfd);return 0;
}
相关文章:

day38 tcp 并发 ,linux下的IO模型----IO多路复用
TCP 并发 由于tcp协议只能实现一对一的通信模式。为了实现一对多,有以下的的处理方式 1. 多进程 开销大 效率低 2. 多线程 创建线程需要耗时 3. 线程池 多线程模型创建线程耗时问题,提前创建 4. IO多路复用 在不创建进程和线程的前提下,对…...

更新Office后,LabVIEW 可执行程序生成失败
问题描述: 在计算机中,LabVIEW 开发的源程序运行正常,但在生成可执行程序时提示以下错误: A VI broke during the build process from being saved without a block diagram. Either open the build specification to include…...

重塑视频创作的格局!ComfyUI-Mochi本地部署教程
一、介绍 mochi是近期Genmo公司开源的先进视频生成模型,具有高保真运动和强大的提示遵循性。此模型的发布极大的缩小了闭源和开源视频生成系统之间的差距。 目前,视频生成模型与现实之间存在巨大差距。其中最影响视频生成的两个关键功能也就是运动质量和…...

如何理解机器学习中的非线性模型 ?
在机器学习中,非线性模型是指能够捕捉输入特征与输出之间复杂非线性关系的一类模型。与线性模型不同,非线性模型的假设更加灵活,因此可以更好地处理真实世界中复杂、多样的数据分布。以下是对非线性模型的理解: 1. 非线性模型的核…...

Web 品质样式表
《Web 品质样式表》是一个重要的指南,旨在帮助开发者提升网站的整体质量和用户体验。以下是一些关键点: 避免使用 <font> 标签:应使用 CSS 来设置显示网页上的字体尺寸。使用 <font> 标签会增加文档的规模,且使每次改…...

计算机网络 笔记 数据链路层3(局域网,广域网,网桥,交换机)
局域网: LAN:在某一区域内由多台计算机互联成的计算机组,使用广播信道 特点: 覆盖范围有限:通常局限在几千米范围内,比如一栋办公楼、一个校园或一个工厂等相对较小的地理区域。 数据传输速率高:一般能达到 10Mbps…...

centos7.6 安装nginx 1.21.3与配置ssl
1 安装依赖 yum -y install gcc zlib zlib-devel pcre-devel openssl openssl-devel2 下载Nginx wget http://nginx.org/download/nginx-1.21.3.tar.gz3 安装目录 mkdir -p /data/apps/nginx4 安装 4.1 创建用户 创建用户nginx使用的nginx用户。 #添加www组 # groupa…...

redis 内存管理和持久化机制
文章目录 前言一、内存管理1、Redis过期策略1.1、惰性过期1.2、定期过期清理频率配置清理流程 2、Redis淘汰策略策略流程算法分析1、LRU2、LFU 二、持久化1、RDB2、AOF 前言 redis 内存管理与持久化 一、内存管理 redis我们的数据都是放在内存里面的,但是内存是有…...

python-42-使用selenium-wire爬取微信公众号下的所有文章列表
文章目录 1 seleniumwire1.1 selenium-wire简介1.2 获取请求和响应信息2 操作2.1 自动获取token和cookie和agent2.3 获取所有清单3 异常解决3.1 请求url失败的问题3.2 访问链接不安全的问题4 参考附录1 seleniumwire Selenium WebDriver本身并不直接提供获取HTTP请求头(header…...

机器人碳钢去毛刺,用大扭去毛刺主轴可轻松去除
在碳钢精密加工的最后阶段,去除毛刺是确保产品质量的关键步骤。面对碳钢这种硬度较高的材料,采用大扭矩的SycoTec去毛刺主轴,成为了行业内的高效解决方案。SycoTec作为精密加工领域的领军品牌,其生产的高速电主轴以其卓越的性能&a…...

day05_Spark SQL
文章目录 day05_Spark SQL课程笔记一、今日课程内容二、Spark SQL 基本介绍(了解)1、什么是Spark SQL**为什么 Spark SQL 是“SQL与大数据之间的桥梁”?****实际意义**为什么要学习Spark SQL呢?**为什么 Spark SQL 像“瑞士军刀”࿱…...

Java线程的异常处理:确保线程安全运行
哈喽,各位小伙伴们,你们好呀,我是喵手。运营社区:C站/掘金/腾讯云/阿里云/华为云/51CTO;欢迎大家常来逛逛 今天我要给大家分享一些自己日常学习到的一些知识点,并以文字的形式跟大家一起交流,互…...

nvim 打造成可用的IDE(2)
上一个 文章写的太长了, 后来再写东西 就一卡一卡的,所以新开一个。 主要是关于 bufferline的。 之前我的界面是这样的。 这个图标很不舒服有。 后来发现是在这里进行配置。 我也不知道,这个配置 我是从哪 抄过来的。 测试结果࿱…...

如何当前正在运行的 Elasticsearch 集群信息
要查看当前正在运行的 Elasticsearch 集群信息,可以通过以下几种方法: 1. 使用 _cluster/health API _cluster/health API 返回集群的健康状态、节点数量、分片状态等信息。可以用 curl 命令直接访问: curl -X GET "http://localhost…...

PHP Filesystem:深入解析与实战应用
PHP Filesystem:深入解析与实战应用 引言 PHP作为一种流行的服务器端编程语言,提供了强大的文件系统操作功能。本文将深入探讨PHP的Filesystem函数,这些函数允许开发者访问和操作服务器上的文件系统。无论是进行基本的文件操作,还是实现复杂的文件管理系统,PHP的Filesys…...

pdf提取文本,表格以及转图片:spire.pdf
文章目录 🐒个人主页:信计2102罗铠威🏅JavaEE系列专栏📖前言:🎀 1. pdfbox1.1导入pdfbox 的maven依赖1.1 提取文本1.2 提取文本表格(可自行加入逻辑处理)1.3 pdf转换成图片代码&…...

jQuery UI 主题
关于“jQuery UI 主题”,我找到了一些有用的信息。 首先,jQuery UI 主题允许开发人员无缝集成UI小部件到他们网站或应用程序的外观和感观。每个插件通过CSS定义样式,包含两层样式信息:标准的jQuery UI CSS框架样式和具体的插件样…...

C# GDI+的DrawString无法绘制Tab键的现象
【啰嗦2句】 现在用C#的人很少了吧?GDI更少了吧?所以这个问题估计也冷门。没关系,分享给特定需要的人也不错。 【问题现象】 工作中开发了一个报告编辑器,实现图文排版等功能,用着没什么问题,直到有一天…...

C# GID+绘制不透明和半透明的线条
绘制线条时,必须将 Pen 对象传递给 DrawLine 类的 Graphics 方法。 Pen 构造函数的参数之一是 Color 对象。 若要绘制不透明的线条,请将颜色的 alpha 分量设置为 255。 若要绘制半透明的线条,请将 alpha 分量设置为从 1 到 254 的任何值。 在…...

L4-Prompt-Delta
Paper List PromptPapers:https://github.com/thunlp/PromptPapersDeltaPapers: https://github.com/thunlp/DeltaPapers Programming Toolkit OpemPrompt: https://github.com/thunlp/OpenPromptOpenDelta: https://github.com/thunlp/OpenDelta 一、传统微调方法࿱…...

Qt 自定义控件(Qt绘图)
一、QPaintEvent绘图事件1、QPaintEvent是Qt框架中一个重要的事件类,专门用于处理绘图事件。 2、当Qt视图组件需要重绘自己的一部分时,就会产生QPaintEvent事件。 3、Qt视图组件重绘自己,通常发生在以下情况: (1)、窗口第一次显示时: 当窗…...

electron 上怎么用node 调用 c++ 提供的方法
背景 在 Electron 上调用 C 代码的场景主要出现在需要执行高性能、低延迟的任务,或者需要与现有的本地 C 库集成时。这些场景往往涉及底层系统交互、性能优化或跨平台兼容性需求。 我们都知道c 的性能和安全性都比JavaScript 要高,但我认为在 Electron …...

Chromium 132 编译指南 Windows 篇 - Git 初始化设置 (四)
1. 引言 在 Chromium 编译指南系列的前几篇文章中,我们已经完成了编译环境的基础设置和关键环境变量的配置。本篇将重点介绍 Git 的安装与初始化配置,这是获取和管理 Chromium 源代码的重要前提。 2. 安装 Git 在 Windows 环境下,Git 并不…...

day03-前端Web-Vue3.0基础
目录 前言1. Vue概述2. 快速入门2.1 需求2.2 步骤2.3 实现 3. Vue指令3.1 介绍3.2 v-for3.2.1 介绍3.2.2 演示3.2.3 v-for的key3.2.4 案例-列表渲染 3.3 v-bind3.3.1 介绍3.3.2 演示3.3.3 案例-图片展示 3.4 v-if & v-show3.4.1 介绍3.4.2 案例-性别职位展示 3.6 v-model3.…...

Windows 下Mamba2 / Vim / Vmamba 环境安装问题记录及解决方法终极版(无需绕过triton)
导航 安装教程导航 Mamba 及 Vim 安装问题参看本人博客:Mamba 环境安装踩坑问题汇总及解决方法(初版)Linux 下Mamba 及 Vim 安装问题参看本人博客:Mamba 环境安装踩坑问题汇总及解决方法(重置版)Windows …...

GitLab本地服务器配置ssh和克隆项目
1. 本地安装好git git链接:https://git-scm.com/downloads/win 无脑点击下一步安装即可,打开Git Bash命令终端如下: 2. 配置本地用户名和邮箱 git config --global user.name "你的名字" git config --global user.email "你的邮箱&quo…...

Win10和11 git/Android Studio遇到filename too long问题的解决
1、打开windows长文件、长路径支持: 可以参考这篇文章: 修改注册表方法: 使用Admin登陆machine,在run中输入regedit并回车; 找到路径 ’Computer -> HKEY_LOCAL_MACHINE -> SYSTEM -> CurrentControlSet -&g…...

【JavaWeb学习Day11】
java程序操作数据库(JDBC) JDBC:(Java DataBase Connectivity),就是使用Java语言操作关系型数据库的一套API。 本质: 1.sun公司官方定义的一套操作所有关系型数据库的规范、即接口。 2.各个数据库厂商去…...

rom定制系列------小米max3安卓12 miui14批量线刷 默认开启usb功能选项 插电自启等
小米Max3是小米公司于2018年7月19日发布的机型。此机型后在没有max新型号。采用全金属一体机身设计,配备6.9英寸全面屏.八核处理器骁龙636,后置双摄像头1200万500万像素,前置800万像素.机型代码 :nitrogen.官方最终版为稳定版12.5…...

CES 2025|美格智能高算力AI模组助力“通天晓”人形机器人震撼发布
当地时间1月7日,2025年国际消费电子展(CES 2025)在美国拉斯维加斯正式开幕。美格智能合作伙伴阿加犀联合高通在展会上面向全球重磅发布人形机器人原型机——通天晓(Ultra Magnus)。该人形机器人内置美格智能基于高通QC…...