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

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

  1. 创建文件描述符集合
    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协议只能实现一对一的通信模式。为了实现一对多&#xff0c;有以下的的处理方式 1. 多进程 开销大 效率低 2. 多线程 创建线程需要耗时 3. 线程池 多线程模型创建线程耗时问题&#xff0c;提前创建 4. IO多路复用 在不创建进程和线程的前提下&#xff0c;对…...

更新Office后,LabVIEW 可执行程序生成失败

问题描述&#xff1a; 在计算机中&#xff0c;LabVIEW 开发的源程序运行正常&#xff0c;但在生成可执行程序时提示以下错误&#xff1a; ​ 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公司开源的先进视频生成模型&#xff0c;具有高保真运动和强大的提示遵循性。此模型的发布极大的缩小了闭源和开源视频生成系统之间的差距。 目前&#xff0c;视频生成模型与现实之间存在巨大差距。其中最影响视频生成的两个关键功能也就是运动质量和…...

如何理解机器学习中的非线性模型 ?

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

Web 品质样式表

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

计算机网络 笔记 数据链路层3(局域网,广域网,网桥,交换机)

局域网: LAN:在某一区域内由多台计算机互联成的计算机组&#xff0c;使用广播信道 特点&#xff1a; 覆盖范围有限&#xff1a;通常局限在几千米范围内&#xff0c;比如一栋办公楼、一个校园或一个工厂等相对较小的地理区域。 数据传输速率高&#xff1a;一般能达到 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我们的数据都是放在内存里面的&#xff0c;但是内存是有…...

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…...

机器人碳钢去毛刺,用大扭去毛刺主轴可轻松去除

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

day05_Spark SQL

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

Java线程的异常处理:确保线程安全运行

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

nvim 打造成可用的IDE(2)

上一个 文章写的太长了&#xff0c; 后来再写东西 就一卡一卡的&#xff0c;所以新开一个。 主要是关于 bufferline的。 之前我的界面是这样的。 这个图标很不舒服有。 后来发现是在这里进行配置。 我也不知道&#xff0c;这个配置 我是从哪 抄过来的。 测试结果&#xff1…...

如何当前正在运行的 Elasticsearch 集群信息

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

PHP Filesystem:深入解析与实战应用

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

pdf提取文本,表格以及转图片:spire.pdf

文章目录 &#x1f412;个人主页&#xff1a;信计2102罗铠威&#x1f3c5;JavaEE系列专栏&#x1f4d6;前言&#xff1a;&#x1f380; 1. pdfbox1.1导入pdfbox 的maven依赖1.1 提取文本1.2 提取文本表格&#xff08;可自行加入逻辑处理&#xff09;1.3 pdf转换成图片代码&…...

jQuery UI 主题

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

C# GDI+的DrawString无法绘制Tab键的现象

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

C# GID+绘制不透明和半透明的线条

绘制线条时&#xff0c;必须将 Pen 对象传递给 DrawLine 类的 Graphics 方法。 Pen 构造函数的参数之一是 Color 对象。 若要绘制不透明的线条&#xff0c;请将颜色的 alpha 分量设置为 255。 若要绘制半透明的线条&#xff0c;请将 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 一、传统微调方法&#xff1…...

网络六边形受到攻击

大家读完觉得有帮助记得关注和点赞&#xff01;&#xff01;&#xff01; 抽象 现代智能交通系统 &#xff08;ITS&#xff09; 的一个关键要求是能够以安全、可靠和匿名的方式从互联车辆和移动设备收集地理参考数据。Nexagon 协议建立在 IETF 定位器/ID 分离协议 &#xff08;…...

连锁超市冷库节能解决方案:如何实现超市降本增效

在连锁超市冷库运营中&#xff0c;高能耗、设备损耗快、人工管理低效等问题长期困扰企业。御控冷库节能解决方案通过智能控制化霜、按需化霜、实时监控、故障诊断、自动预警、远程控制开关六大核心技术&#xff0c;实现年省电费15%-60%&#xff0c;且不改动原有装备、安装快捷、…...

STM32F4基本定时器使用和原理详解

STM32F4基本定时器使用和原理详解 前言如何确定定时器挂载在哪条时钟线上配置及使用方法参数配置PrescalerCounter ModeCounter Periodauto-reload preloadTrigger Event Selection 中断配置生成的代码及使用方法初始化代码基本定时器触发DCA或者ADC的代码讲解中断代码定时启动…...

全球首个30米分辨率湿地数据集(2000—2022)

数据简介 今天我们分享的数据是全球30米分辨率湿地数据集&#xff0c;包含8种湿地亚类&#xff0c;该数据以0.5X0.5的瓦片存储&#xff0c;我们整理了所有属于中国的瓦片名称与其对应省份&#xff0c;方便大家研究使用。 该数据集作为全球首个30米分辨率、覆盖2000–2022年时间…...

linux arm系统烧录

1、打开瑞芯微程序 2、按住linux arm 的 recover按键 插入电源 3、当瑞芯微检测到有设备 4、松开recover按键 5、选择升级固件 6、点击固件选择本地刷机的linux arm 镜像 7、点击升级 &#xff08;忘了有没有这步了 估计有&#xff09; 刷机程序 和 镜像 就不提供了。要刷的时…...

跨链模式:多链互操作架构与性能扩展方案

跨链模式&#xff1a;多链互操作架构与性能扩展方案 ——构建下一代区块链互联网的技术基石 一、跨链架构的核心范式演进 1. 分层协议栈&#xff1a;模块化解耦设计 现代跨链系统采用分层协议栈实现灵活扩展&#xff08;H2Cross架构&#xff09;&#xff1a; 适配层&#xf…...

论文解读:交大港大上海AI Lab开源论文 | 宇树机器人多姿态起立控制强化学习框架(一)

宇树机器人多姿态起立控制强化学习框架论文解析 论文解读&#xff1a;交大&港大&上海AI Lab开源论文 | 宇树机器人多姿态起立控制强化学习框架&#xff08;一&#xff09; 论文解读&#xff1a;交大&港大&上海AI Lab开源论文 | 宇树机器人多姿态起立控制强化…...

Ascend NPU上适配Step-Audio模型

1 概述 1.1 简述 Step-Audio 是业界首个集语音理解与生成控制一体化的产品级开源实时语音对话系统&#xff0c;支持多语言对话&#xff08;如 中文&#xff0c;英文&#xff0c;日语&#xff09;&#xff0c;语音情感&#xff08;如 开心&#xff0c;悲伤&#xff09;&#x…...

让AI看见世界:MCP协议与服务器的工作原理

让AI看见世界&#xff1a;MCP协议与服务器的工作原理 MCP&#xff08;Model Context Protocol&#xff09;是一种创新的通信协议&#xff0c;旨在让大型语言模型能够安全、高效地与外部资源进行交互。在AI技术快速发展的今天&#xff0c;MCP正成为连接AI与现实世界的重要桥梁。…...

【论文阅读28】-CNN-BiLSTM-Attention-(2024)

本文把滑坡位移序列拆开、筛优质因子&#xff0c;再用 CNN-BiLSTM-Attention 来动态预测每个子序列&#xff0c;最后重构出总位移&#xff0c;预测效果超越传统模型。 文章目录 1 引言2 方法2.1 位移时间序列加性模型2.2 变分模态分解 (VMD) 具体步骤2.3.1 样本熵&#xff08;S…...