IO多路复用中select的TCP服务器模型和poll服务模型
select的TCP服务器模型
服务器端
#include <head.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <arpa/inet.h>
#include <unistd.h>
#include <sys/select.h>
#include <sys/time.h>#define PORT 6666 //1024~49151
#define IP "192.168.122.120" //ifconfig查看本机IP
int main(int argc, const char *argv[])
{//创建流式套接字int sfd = socket(AF_INET,SOCK_STREAM,0);if(sfd < 0){ERRO_MES("socket");return -1;}printf("sfd = %d\n",sfd);//绑定服务器的IP和端口--->必须绑定//填充地址信息结构体,真实的地址信息结构体根据地质族制定//AF_INET: man 7 ip;struct sockaddr_in sin;sin.sin_family = AF_INET;//必须填AF_INET;sin.sin_port = htons(PORT); //端口号:1024~49151;sin.sin_addr.s_addr = inet_addr(IP); //本机IP ifconfig查看;if(bind(sfd,(struct sockaddr*)&sin,sizeof(sin)) < 0){ERRO_MES("bind");return -1;}printf("bind success\n");//将套接字设置为被动监听状态if(listen(sfd,10) < 0){ERRO_MES("listen");return -1;}printf("listen success\n");//设置允许端口号被快速复用int reuse = 1;if(setsockopt(sfd, SOL_SOCKET, SO_REUSEADDR, &reuse, sizeof(reuse)) < 0){ERRO_MES("setsockopt");return -1;}printf("允许端口快速重用成功\n");//从已完成链接的队列中获取一个客户端信息,生成一个新的文件//该文件描述符才是与客户端通信的文件描述符struct sockaddr_in cin;socklen_t addrlen = sizeof(cin);struct sockaddr_in saveCin[1024-3];//创建一个读集合fd_set readfds,tempfds;//初始化文件描述符FD_ZERO(&readfds);FD_ZERO(&tempfds);//将需要的文件描述符添加到读集合中FD_SET(sfd,&readfds);FD_SET(0,&readfds);//确定最大文件描述符int maxfd = sfd;int s_res = -1;char buf[128]="";ssize_t res = 0;int newfd = -1;while(1){tempfds = readfds;//调用IO多路复用函数 ,select()s_res = select(maxfd+1, &tempfds, NULL, NULL, NULL);if(s_res < 0){ERRO_MES("select");return -1;}else if(0 == s_res){printf("超时操作\n");break;}//判断是哪个文件描述符准备就绪,走对应处理函数即可for(int i=0; i<=maxfd; i++){if(FD_ISSET(i, &tempfds) == 0)continue;if(0 == i){printf("触发键盘输入事件\n");fgets(buf,sizeof(buf),stdin);buf[strlen(buf)-1] = 0;printf(": %s\n",buf);}else if(sfd == i){printf("触发客户端连接事件\n");newfd = accept(sfd,(struct sockaddr*)&cin,&addrlen);if(newfd < 0){ERRO_MES("accept");return -1;}printf("[%s : %d] newfd = %d,客户端链接成功\n",\inet_ntoa(cin.sin_addr),ntohs(cin.sin_port),newfd);saveCin[newfd-3] = cin;//将newfd添加到集合FD_SET(newfd, &readfds);maxfd = newfd>sfd ? newfd : sfd;}else{printf("触发客户端交互事件\n");bzero(buf,sizeof(buf));//接收数据res = recv(i,buf,sizeof(buf),0);if(res < 0){ERRO_MES("recv");return -1;}else if(0 == res){printf("[%s : %d] newfd = %d,客户下线\n",\inet_ntoa(saveCin[i-3].sin_addr),ntohs(saveCin[i-3].sin_port),i);//关闭下线客户端的文件描述符close(i);//将下线客户端的文件描述符从集合中剔除FD_CLR(i,&readfds);//更新maxfdwhile(FD_ISSET(maxfd,&readfds) == 0 && maxfd-- >=0);continue;}printf("[%s : %d] newfd :%d\t buf = %s\n"\,inet_ntoa(saveCin[i-3].sin_addr),ntohs(saveCin[i-3].sin_port),i,buf);//发送数据strcat(buf,"----");if(send(newfd,buf,sizeof(buf),0) < 0){ERRO_MES("send");return -1;}printf("send success\n");}}}close(sfd);close(newfd);return 0;
}
客户端
#include <head.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <arpa/inet.h>
#include <unistd.h>
#include <sys/select.h>
#include <sys/time.h>#define PORT 6666 //1024~49151
#define IP "192.168.122.120" //ifconfig查看本机IP
int main(int argc, const char *argv[])
{//创建流式套接字int cfd = socket(AF_INET,SOCK_STREAM,0);if(cfd < 0){ERRO_MES("socket");return -1;}printf("cfd = %d\n",cfd);//绑定服务器的IP和端口--->非必须绑定//填充地址信息结构体,真实的地址信息结构体根据地质族制定//AF_INET: man 7 ip;struct sockaddr_in sin;sin.sin_family = AF_INET;//必须填AF_INET;sin.sin_port = htons(PORT); //端口号:填服务器绑定的端口号;sin.sin_addr.s_addr = inet_addr(IP);//IP地址;服务器绑定的IP地址if(connect(cfd,(struct sockaddr*)&sin,sizeof(sin)) < 0){ERRO_MES("connect");return -1;}printf("连接成功\n");//创建一个读集合fd_set readfds,tempfds;//初始化集合FD_ZERO(&readfds);FD_ZERO(&tempfds);//将需要的文件描述符添加到读集合FD_SET(0,&readfds);FD_SET(cfd,&readfds);char buf[128]="";ssize_t res = 0;int s_res = -1;int maxfd = cfd;while(1){tempfds = readfds;s_res = select(maxfd+1,&tempfds,NULL,NULL,NULL);if(s_res < 0){ERRO_MES("select");return -1;}else if(0 == s_res){printf("time out...\n");break;}if(FD_ISSET(0,&tempfds)){printf("触发键盘输入事件\n");bzero(buf,sizeof(buf));fgets(buf,sizeof(buf),stdin);buf[strlen(buf)-1] = 0;printf(": %s\n",buf);if(send(cfd,buf,sizeof(buf),0) < 0){ERRO_MES("send");return -1;}printf("send success\n");}if(FD_ISSET(cfd,&tempfds)){printf("触发服务器交互事件\n");bzero(buf,sizeof(buf));//接收数据res = recv(cfd,buf,sizeof(buf),0);if(res < 0){ERRO_MES("recv");return -1;}else if(0 == res){printf("[%s : %d] cfd = %d,客户下线\n",IP,PORT,cfd);break;}printf("[%s : %d] cfd :%d\t buf = %s\n",IP,PORT,cfd,buf);}}close(cfd);return 0;
}
poll客户端
#include <head.h>
#include <arpa/inet.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <poll.h>
#include <unistd.h>#define PORT 6666
#define IP "192.168.122.120"
int main(int argc, const char *argv[])
{//创建流式套接字int cfd = socket(AF_INET,SOCK_STREAM,0);if(cfd < 0){ERRO_MES("socket");return -1;}printf("cfd = %d\n",cfd);//绑定客户端的IP和端口 ----->客户端(非必须)//若不绑定,则操作系统会给客户端绑定上客户端所在的主机IP,以及随机端口(49152~65535)//填充服务器的地址信息结构体,真实的地址信息结构体根据地址族指定//AF_INET:man 7 ip//要连接哪个服务器,就填对应服务器的IP和端口struct sockaddr_in sin;sin.sin_family = AF_INET; //必须填AF_INETsin.sin_port = htons(PORT); //端口号:填服务器绑定端口号sin.sin_addr.s_addr = inet_addr(IP); //IP地址:服务器绑定的IP地址//连接服务器if(connect(cfd,(struct sockaddr*)&sin,sizeof(sin)) < 0){ERRO_MES("connect");return -1;}printf("connect success\n");//定义集合struct pollfd fds[2];//将需要监测的文件描述符添加到集合中fds[0].fd = 0; //指定监测0号文件描述符fds[0].events = POLLIN; //监测读事件fds[1].fd = cfd; //指定监测cfd号文件描述符fds[1].events = POLLIN; //监测读事件char buf[128] = "";ssize_t res = 0;int p_res = -1;while(1){p_res = poll(fds,2,-1);if(p_res < 0){ERRO_MES("poll");return -1;}else if(0 == p_res){printf("time out...\n");break;}//能运行到当前位置,代表集合中有文件描述符准备就绪//判断是哪个文件描述符准备就绪,走对应处理函数//判断集合中的每个文件描述符的revents中是否有POLLIN//从revents中将代表POLLIN的那一位单独提取出来,判断是1还是0if((fds[0].revents & POLLIN) != 0){printf("触发键盘输入事件\n");bzero(buf,sizeof(buf));fgets(buf,sizeof(buf),stdin);buf[strlen(buf)-1] = 0;//发送数据if(send(cfd, buf,sizeof(buf),0) < 0){ERRO_MES("send");return -1;}printf("send success\n");}if(fds[1].revents & POLLIN){printf("触发服务器交互事件\n");bzero(buf,sizeof(buf));//接收数据res = recv(cfd,buf,sizeof(buf),0);if(res < 0){ERRO_MES("recv");return -1;}else if(0 == res){printf("[%s : %d] cfd= %d 服务器掉线\n",IP,PORT,cfd);break;}printf("[%s : %d] cfd= %d : %s\n",IP,PORT,cfd,buf);}}close(cfd);return 0;
}
相关文章:
IO多路复用中select的TCP服务器模型和poll服务模型
select的TCP服务器模型 服务器端 #include <head.h> #include <sys/types.h> #include <sys/socket.h> #include <arpa/inet.h> #include <unistd.h> #include <sys/select.h> #include <sys/time.h>#define PORT 6666 //1024~4…...

AI工程师招募;60+开发者AI工具清单;如何用AI工具读懂插件源码;开发者出海解读;斯坦福LLM课程 | ShowMeAI日报
👀日报&周刊合集 | 🎡生产力工具与行业应用大全 | 🧡 点赞关注评论拜托啦! 🤖 一则AI工程师招募信息:新领域需要新技能 Vision Flow (目的涌现) 是一家基于 AGI 原生技术的创业公司,是全球探…...
Mysql 使用JSON_SEARCH函数 判断多表查询时,某个拼接字段是否包含另外一个字段
场景 两个表管理查询 关联字段为A表id, B表的ids A表id是正常的整数, B的ids是id拼接成的字符类型, 格式是111,222,333这样的. A: B: id ids11 11,22,3322 33,44,5533 …...

C++头文件
C头文件 一般头文件特殊头文件windows.hbits/stdc.h 一般头文件 C头文件是一种包含预定义函数、类和变量声明的文件。它们通常用于在源代码文件中引入外部库或模块的功能。 头文件的作用是提供程序所需的声明信息,以便在源代码文件中使用这些声明。当你在源代码文…...

无脑入门pytorch系列(四)—— scatter_
本系列教程适用于没有任何pytorch的同学(简单的python语法还是要的),从代码的表层出发挖掘代码的深层含义,理解具体的意思和内涵。pytorch的很多函数看着非常简单,但是其中包含了很多内容,不了解其中的意思…...

【Spring源码】Spring扩展点及顺序
Spring扩展点及顺序 01-调用BeanFactoryPostProcessor的构造器 02-调用了BeanFactoryPostProcessor的postProcessBeanFactory 03-调用了BeanPostProcessor构造器 04-调用InstantiationAwareBeanPostProcessor构造方法 05-调用了InstantiationAwareBeanPostProcessor接口的Befo…...

广州华锐互动:3D数字孪生开发编辑器助力企业高效开发数字孪生应用
3D数字孪生开发编辑器是一种新兴的技术,它可以帮助企业更好地管理和维护其物联网设备。这些工具可以帮助企业实现对设备的实时监控、故障排除和优化,从而提高生产效率和降低成本。 数字孪生系统是一种将物理世界与数字世界相结合的技术,它可以…...

【脚踢数据结构】图(纯享版)
(꒪ꇴ꒪ ),Hello我是祐言QAQ我的博客主页:C/C语言,Linux基础,ARM开发板,软件配置等领域博主🌍快上🚘,一起学习,让我们成为一个强大的攻城狮!送给自己和读者的…...
[leetcode] 707 设计链表
707. 设L计链表 中等 902 相关企业 你可以选择使用单链表或者双链表,设计并实现自己的链表。 单链表中的节点应该具备两个属性:val 和 next 。val 是当前节点的值,next 是指向下一个节点的指针/引用。 如果是双向链表,则还需…...

JIRA:项目管理的秘密武器
引言 在当今动态且快速变化的商业环境中,项目管理已经成为任何组织成功的关键因素。能够有效地管理项目,保证项目在设定的时间和预算内按照预期的质量完成,是每个项目经理的目标。为了实现这个目标,项目经理需要依赖强大的工具&a…...

ARM 作业1
一、思维导图 二、 1. 2. .text 文本段 .globl _start 声明_start:mov r0,#0mov r1,#0fun:cmp r1,#100bhi stopadd r0,r0,r1add r1,r1,#1b fun stop:b stop .end...

【解析postman工具的使用---基础篇】
postman前端请求详解 主界面1.常见类型的接口请求1.1 查询参数的接口请求1.1.1 什么是查询参数?1.1.2 postman如何请求 1.2 ❤表单类型的接口请求1.2.1 复习下http请求1.2.2❤ 什么是表单 1.3 上传文件的表单请求1.4❤ json类型的接口请求 2. 响应接口数据分析2.1 postman的响…...

Elasticsearch:如何在 Ubuntu 上安装多个节点的 Elasticsearch 集群 - 8.x
Elasticsearch 是一个强大且可扩展的搜索和分析引擎,可用于索引和搜索大量数据。 Elasticsearch 通常用于集群环境中,以提高性能、提供高可用性并实现数据冗余。 在本文中,我们将讨论如何在 Ubuntu 20.04 上安装和配置具有多节点集群的 Elast…...

记录win 7旗舰版 “VMware Alias Manager and Ticket Service‘(VGAuhService)启动失败。
记录win 7旗舰版 "VMware Alias Manager and Ticket Service’(VGAuhService)启动失败。 描述如图 https://learn.microsoft.com/zh-CN/cpp/windows/latest-supported-vc-redist?viewmsvc-140#visual-studio-2015-2017-2019-and-2022 安装对应版本的VC 库就可以解决问…...

git 开发环境配置
系统:Mac OS 1、下载git,官网已经推荐使用命令下载。 /bin/zsh -c "$(curl -fsSL https://gitee.com/cunkai/HomebrewCN/raw/master/Homebrew.sh) 2、验证git是否安装成功 git --version 3、配置本地git全局变量 git config --global user.n…...

Tableau画图
目录 蝴蝶图 四象图 排序图 盒型图/散点图 圆环图 火柴图 直方图 瀑布图 地理图 面积图 树地图 面积图 条形图 词云图 双轴图 填充地图 tableau2023.2 须知 蝴蝶图 拉好数据之后 创建新字段正负销售额,并拖入第一个颜色标记卡 四象图 智能推荐 散…...

nginx上web服务的基本安全优化、服务性能优化、访问日志优化、目录资源优化和防盗链配置简介
一.基本安全优化 1.隐藏nginx软件版本信息 2.更改源码来隐藏软件名和版本 (1)修改第一个文件(核心头文件),在nginx安装目录下找到这个文件并修改 (2)第二个文件 (3)…...
himall3.0商城源码
目录 1 himall3.0商城源码 1.1 /// 获取待评价订单数量 1.2 /// 保存支付订单信息,生成支付订单 1.3 /// 取最近time分钟内的满足打印的订单数据 himall3.0商城源码 /// <summary>...

【LeetCode75】第二十九题 删除链表的中间节点
目录 题目: 示例; 分析: 代码: 题目: 示例; 分析: 给我们一个链表,让我们把链表中间的节点删了。 那么最直观最基础的办法是遍历两边链表,第一遍拿到链表长度,第二次把链表中间节点删了。 这个暴力做法我没事过…...

Floyd(多源汇最短路)
Floyd求最短路 给定一个 n 个点 m 条边的有向图,图中可能存在重边和自环,边权可能为负数。 再给定 k 个询问,每个询问包含两个整数 x 和 y,表示查询从点 x 到点 y 的最短距离,如果路径不存在,则输出 impo…...

【WiFi帧结构】
文章目录 帧结构MAC头部管理帧 帧结构 Wi-Fi的帧分为三部分组成:MAC头部frame bodyFCS,其中MAC是固定格式的,frame body是可变长度。 MAC头部有frame control,duration,address1,address2,addre…...
Java多线程实现之Thread类深度解析
Java多线程实现之Thread类深度解析 一、多线程基础概念1.1 什么是线程1.2 多线程的优势1.3 Java多线程模型 二、Thread类的基本结构与构造函数2.1 Thread类的继承关系2.2 构造函数 三、创建和启动线程3.1 继承Thread类创建线程3.2 实现Runnable接口创建线程 四、Thread类的核心…...
鸿蒙DevEco Studio HarmonyOS 5跑酷小游戏实现指南
1. 项目概述 本跑酷小游戏基于鸿蒙HarmonyOS 5开发,使用DevEco Studio作为开发工具,采用Java语言实现,包含角色控制、障碍物生成和分数计算系统。 2. 项目结构 /src/main/java/com/example/runner/├── MainAbilitySlice.java // 主界…...
Angular微前端架构:Module Federation + ngx-build-plus (Webpack)
以下是一个完整的 Angular 微前端示例,其中使用的是 Module Federation 和 npx-build-plus 实现了主应用(Shell)与子应用(Remote)的集成。 🛠️ 项目结构 angular-mf/ ├── shell-app/ # 主应用&…...
Hive 存储格式深度解析:从 TextFile 到 ORC,如何选对数据存储方案?
在大数据处理领域,Hive 作为 Hadoop 生态中重要的数据仓库工具,其存储格式的选择直接影响数据存储成本、查询效率和计算资源消耗。面对 TextFile、SequenceFile、Parquet、RCFile、ORC 等多种存储格式,很多开发者常常陷入选择困境。本文将从底…...

VM虚拟机网络配置(ubuntu24桥接模式):配置静态IP
编辑-虚拟网络编辑器-更改设置 选择桥接模式,然后找到相应的网卡(可以查看自己本机的网络连接) windows连接的网络点击查看属性 编辑虚拟机设置更改网络配置,选择刚才配置的桥接模式 静态ip设置: 我用的ubuntu24桌…...

iview框架主题色的应用
1.下载 less要使用3.0.0以下的版本 npm install less2.7.3 npm install less-loader4.0.52./src/config/theme.js文件 module.exports {yellow: {theme-color: #FDCE04},blue: {theme-color: #547CE7} }在sass中使用theme配置的颜色主题,无需引入,直接可…...

Scrapy-Redis分布式爬虫架构的可扩展性与容错性增强:基于微服务与容器化的解决方案
在大数据时代,海量数据的采集与处理成为企业和研究机构获取信息的关键环节。Scrapy-Redis作为一种经典的分布式爬虫架构,在处理大规模数据抓取任务时展现出强大的能力。然而,随着业务规模的不断扩大和数据抓取需求的日益复杂,传统…...

零知开源——STM32F103RBT6驱动 ICM20948 九轴传感器及 vofa + 上位机可视化教程
STM32F1 本教程使用零知标准板(STM32F103RBT6)通过I2C驱动ICM20948九轴传感器,实现姿态解算,并通过串口将数据实时发送至VOFA上位机进行3D可视化。代码基于开源库修改优化,适合嵌入式及物联网开发者。在基础驱动上新增…...
redis和redission的区别
Redis 和 Redisson 是两个密切相关但又本质不同的技术,它们扮演着完全不同的角色: Redis: 内存数据库/数据结构存储 本质: 它是一个开源的、高性能的、基于内存的 键值存储数据库。它也可以将数据持久化到磁盘。 核心功能: 提供丰…...