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

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日报

&#x1f440;日报&周刊合集 | &#x1f3a1;生产力工具与行业应用大全 | &#x1f9e1; 点赞关注评论拜托啦&#xff01; &#x1f916; 一则AI工程师招募信息&#xff1a;新领域需要新技能 Vision Flow (目的涌现) 是一家基于 AGI 原生技术的创业公司&#xff0c;是全球探…...

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头文件是一种包含预定义函数、类和变量声明的文件。它们通常用于在源代码文件中引入外部库或模块的功能。 头文件的作用是提供程序所需的声明信息&#xff0c;以便在源代码文件中使用这些声明。当你在源代码文…...

无脑入门pytorch系列(四)—— scatter_

本系列教程适用于没有任何pytorch的同学&#xff08;简单的python语法还是要的&#xff09;&#xff0c;从代码的表层出发挖掘代码的深层含义&#xff0c;理解具体的意思和内涵。pytorch的很多函数看着非常简单&#xff0c;但是其中包含了很多内容&#xff0c;不了解其中的意思…...

【Spring源码】Spring扩展点及顺序

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

广州华锐互动:3D数字孪生开发编辑器助力企业高效开发数字孪生应用

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

【脚踢数据结构】图(纯享版)

(꒪ꇴ꒪ )&#xff0c;Hello我是祐言QAQ我的博客主页&#xff1a;C/C语言&#xff0c;Linux基础&#xff0c;ARM开发板&#xff0c;软件配置等领域博主&#x1f30d;快上&#x1f698;&#xff0c;一起学习&#xff0c;让我们成为一个强大的攻城狮&#xff01;送给自己和读者的…...

[leetcode] 707 设计链表

707. 设L计链表 中等 902 相关企业 你可以选择使用单链表或者双链表&#xff0c;设计并实现自己的链表。 单链表中的节点应该具备两个属性&#xff1a;val 和 next 。val 是当前节点的值&#xff0c;next 是指向下一个节点的指针/引用。 如果是双向链表&#xff0c;则还需…...

JIRA:项目管理的秘密武器

引言 在当今动态且快速变化的商业环境中&#xff0c;项目管理已经成为任何组织成功的关键因素。能够有效地管理项目&#xff0c;保证项目在设定的时间和预算内按照预期的质量完成&#xff0c;是每个项目经理的目标。为了实现这个目标&#xff0c;项目经理需要依赖强大的工具&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 是一个强大且可扩展的搜索和分析引擎&#xff0c;可用于索引和搜索大量数据。 Elasticsearch 通常用于集群环境中&#xff0c;以提高性能、提供高可用性并实现数据冗余。 在本文中&#xff0c;我们将讨论如何在 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 开发环境配置

系统&#xff1a;Mac OS 1、下载git&#xff0c;官网已经推荐使用命令下载。 /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 须知 蝴蝶图 拉好数据之后 创建新字段正负销售额&#xff0c;并拖入第一个颜色标记卡 四象图 智能推荐 散…...

nginx上web服务的基本安全优化、服务性能优化、访问日志优化、目录资源优化和防盗链配置简介

一.基本安全优化 1.隐藏nginx软件版本信息 2.更改源码来隐藏软件名和版本 &#xff08;1&#xff09;修改第一个文件&#xff08;核心头文件&#xff09;&#xff0c;在nginx安装目录下找到这个文件并修改 &#xff08;2&#xff09;第二个文件 &#xff08;3&#xff09;…...

himall3.0商城源码

目录 1 himall3.0商城源码 1.1 /// 获取待评价订单数量 1.2 /// 保存支付订单信息,生成支付订单 1.3 /// 取最近time分钟内的满足打印的订单数据 himall3.0商城源码 /// <summary>...

【LeetCode75】第二十九题 删除链表的中间节点

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

Floyd(多源汇最短路)

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

盘古信息PCB行业解决方案:以全域场景重构,激活智造新未来

一、破局&#xff1a;PCB行业的时代之问 在数字经济蓬勃发展的浪潮中&#xff0c;PCB&#xff08;印制电路板&#xff09;作为 “电子产品之母”&#xff0c;其重要性愈发凸显。随着 5G、人工智能等新兴技术的加速渗透&#xff0c;PCB行业面临着前所未有的挑战与机遇。产品迭代…...

PPT|230页| 制造集团企业供应链端到端的数字化解决方案:从需求到结算的全链路业务闭环构建

制造业采购供应链管理是企业运营的核心环节&#xff0c;供应链协同管理在供应链上下游企业之间建立紧密的合作关系&#xff0c;通过信息共享、资源整合、业务协同等方式&#xff0c;实现供应链的全面管理和优化&#xff0c;提高供应链的效率和透明度&#xff0c;降低供应链的成…...

376. Wiggle Subsequence

376. Wiggle Subsequence 代码 class Solution { public:int wiggleMaxLength(vector<int>& nums) {int n nums.size();int res 1;int prediff 0;int curdiff 0;for(int i 0;i < n-1;i){curdiff nums[i1] - nums[i];if( (prediff > 0 && curdif…...

【CSS position 属性】static、relative、fixed、absolute 、sticky详细介绍,多层嵌套定位示例

文章目录 ★ position 的五种类型及基本用法 ★ 一、position 属性概述 二、position 的五种类型详解(初学者版) 1. static(默认值) 2. relative(相对定位) 3. absolute(绝对定位) 4. fixed(固定定位) 5. sticky(粘性定位) 三、定位元素的层级关系(z-i…...

【Java_EE】Spring MVC

目录 Spring Web MVC ​编辑注解 RestController RequestMapping RequestParam RequestParam RequestBody PathVariable RequestPart 参数传递 注意事项 ​编辑参数重命名 RequestParam ​编辑​编辑传递集合 RequestParam 传递JSON数据 ​编辑RequestBody ​…...

技术栈RabbitMq的介绍和使用

目录 1. 什么是消息队列&#xff1f;2. 消息队列的优点3. RabbitMQ 消息队列概述4. RabbitMQ 安装5. Exchange 四种类型5.1 direct 精准匹配5.2 fanout 广播5.3 topic 正则匹配 6. RabbitMQ 队列模式6.1 简单队列模式6.2 工作队列模式6.3 发布/订阅模式6.4 路由模式6.5 主题模式…...

基于IDIG-GAN的小样本电机轴承故障诊断

目录 🔍 核心问题 一、IDIG-GAN模型原理 1. 整体架构 2. 核心创新点 (1) ​梯度归一化(Gradient Normalization)​​ (2) ​判别器梯度间隙正则化(Discriminator Gradient Gap Regularization)​​ (3) ​自注意力机制(Self-Attention)​​ 3. 完整损失函数 二…...

并发编程 - go版

1.并发编程基础概念 进程和线程 A. 进程是程序在操作系统中的一次执行过程&#xff0c;系统进行资源分配和调度的一个独立单位。B. 线程是进程的一个执行实体,是CPU调度和分派的基本单位,它是比进程更小的能独立运行的基本单位。C.一个进程可以创建和撤销多个线程;同一个进程中…...

LangFlow技术架构分析

&#x1f527; LangFlow 的可视化技术栈 前端节点编辑器 底层框架&#xff1a;基于 &#xff08;一个现代化的 React 节点绘图库&#xff09; 功能&#xff1a; 拖拽式构建 LangGraph 状态机 实时连线定义节点依赖关系 可视化调试循环和分支逻辑 与 LangGraph 的深…...

SpringAI实战:ChatModel智能对话全解

一、引言&#xff1a;Spring AI 与 Chat Model 的核心价值 &#x1f680; 在 Java 生态中集成大模型能力&#xff0c;Spring AI 提供了高效的解决方案 &#x1f916;。其中 Chat Model 作为核心交互组件&#xff0c;通过标准化接口简化了与大语言模型&#xff08;LLM&#xff0…...