当前位置: 首页 > 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…...

Pycharm找不到Conda可执行文件路径(Pycharm无法导入Anaconda已有环境)

在使用Pycharm时发现无法导入Anaconda创建好的环境&#xff0c;会出现找不到Conda可执行文件路径的问题。 解决 在输入框内输入D:\anaconda3\Scripts\conda.exe&#xff0c;点击加载环境。 注意前面目录是自己Anaconda的安装位置&#xff0c;之后就可以找到Anaconda的现有环…...

国产之光:讯飞星火最新大模型V2.0

大家好&#xff0c;我是herosunly。985院校硕士毕业&#xff0c;现担任算法研究员一职&#xff0c;热衷于机器学习算法研究与应用。曾获得阿里云天池比赛第一名&#xff0c;CCF比赛第二名&#xff0c;科大讯飞比赛第三名。拥有多项发明专利。对机器学习和深度学习拥有自己独到的…...

通讯录实现【C语言】

目录 前言 一、整体逻辑分析 二、实现步骤 1、创建菜单和多次操作问题 2、创建通讯录 3、初始化通讯录 4、添加联系人 5、显示联系人 6、删除指定联系人 ​7、查找指定联系人 8、修改联系人信息 9、排序联系人信息 三、全部源码 前言 我们上期已经详细的介绍了自定…...

pcl欧式聚类

欧式聚类实现方法大致是&#xff1a; 1、找到空间中某点 p 1 p_1 p1​&#xff0c;用KD-Tree找到离他最近的n个点&#xff0c;判断这n个点到 p 1 p_1 p1​的距离。将距离小于阈值r的点 p 2 、 p 3 、 p 4 p_2、p_3、p_4 p2​、p3​、p4​…放在类Q里 2、在 Q ( p 1 ) Q(p_1…...

macOS Ventura 13.5.1(22G90)发布(附黑/白苹果系统镜像地址)

系统镜像下载&#xff1a;百度&#xff1a;黑果魏叔 系统介绍 黑果魏叔 8 月 18 日消息&#xff0c;苹果今日向 Mac 电脑用户推送了 macOS 13.5.1 更新&#xff08;内部版本号&#xff1a;22G90&#xff09;&#xff0c;本次更新距离上次发布隔了 24 天。 本次更新重点修复了…...

分布式监控平台——Zabbix

市场上常用的监控软件&#xff1a; 传统运维&#xff1a;zabbix、 Nagios 一、zabbix概述 作为一个运维&#xff0c;需要会使用监控系统查看服务器状态以及网站流量指标&#xff0c;利用监控系统的数据去了解上线发布的结果&#xff0c;和网站的健康状态。 利用一个优秀的监…...

【OpenGauss源码学习 —— 列存储(创建表)】

列存储 什么是列存储&#xff1f;语法实现语法格式参数说明示例源码分析&#xff08;创建表&#xff09;语法层&#xff08;Gram.y&#xff09;子模块&#xff08;utility.cpp&#xff09; 总结 声明&#xff1a;本文的部分内容参考了他人的文章。在编写过程中&#xff0c;我们…...

Jenkins 监控dist.zip文件内容发生变化 触发自动部署

为Jenkins添加plugin http://xx:xx/manage 创建一个任务 构建触发器 每3分钟扫描一次&#xff0c;发现指定文件build.zip文件的MD5发生变化后 触发任务...

Linux系列讲解 —— FTP协议的应用

简单介绍一下FTP文件传输协议在linux系统中的应用。 目录 0. 基本概念1. FTP Server1.1 安装FTP Server1.2 FTP Server开启和关闭1.3 查看FTP Server是否开启1.4 FTP服务器配置 2. FTP Client2.1 lftp2.2 ftp2.3 sftp2.4 文件资源管理器集成的ftp和sftp 3. ftp常用命令 0. 基本…...

Rancher-RKE-install 部署k8s集群

一、为什么用Rancher-RKE-install 1.CNCF认证的k8s安装程序。 2.有中文文档。 二、安装步骤 1.下载Rancher-Rke的二进制包-下面是项目的地址 GitHub - rancher/rke: Rancher Kubernetes Engine (RKE), an extremely simple, lightning fast Kubernetes distrib…...