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

3个方法解决小说断更难题:Yuedu书源库让你实现阅读自由

3个方法解决小说断更难题&#xff1a;Yuedu书源库让你实现阅读自由 【免费下载链接】Yuedu &#x1f4da;「阅读」APP 精品书源&#xff08;网络小说&#xff09; 项目地址: https://gitcode.com/gh_mirrors/yu/Yuedu 你是否经历过这样的时刻&#xff1a;深夜追更的小说…...

别再只调headingPitchRoll了!深入Cesium矩阵变换,从原理到代码理解模型朝向控制

深入Cesium矩阵变换&#xff1a;从数学原理到模型朝向控制的实战指南 在三维地理可视化领域&#xff0c;精确控制模型朝向一直是开发者面临的挑战。许多开发者习惯使用现成的headingPitchRoll方法&#xff0c;但当遇到复杂场景如极地附近模型旋转异常时&#xff0c;往往束手无策…...

实战应用:从零到一,使用快马构建资料更新内容管理系统的完整案例

实战应用&#xff1a;从零到一&#xff0c;使用快马构建资料更新内容管理系统的完整案例 最近接手了一个资料大全的版本更新管理需求&#xff0c;需要搭建一个简单高效的内容管理系统。经过一番摸索&#xff0c;我发现用InsCode(快马)平台可以快速实现这个功能&#xff0c;整个…...

OpenClaw低代码方案:Qwen3-32B将Excel需求转为自动化流程

OpenClaw低代码方案&#xff1a;Qwen3-32B将Excel需求转为自动化流程 1. 从Excel到ERP的自动化困境 上周市场部的同事又来找我帮忙了。他们每天要手动将几十份Excel表格里的客户订单录入到公司老旧的ERP系统里——这个上世纪风格的绿色界面软件&#xff0c;既没有批量导入功能…...

Linux网络开发实战:如何用MDIO总线扫描PHY设备并注册驱动(附完整代码解析)

Linux网络开发实战&#xff1a;MDIO总线扫描PHY设备与驱动注册全解析 在嵌入式Linux网络设备开发中&#xff0c;PHY芯片作为物理层接口的核心组件&#xff0c;其驱动加载和设备管理机制直接影响网络功能的稳定性。MDIO总线作为连接MAC控制器与PHY芯片的标准接口&#xff0c;其扫…...

DanKoe 视频笔记:《百万美元创意者》:如何将你的兴趣货币化 [特殊字符]

在本节课中&#xff0c;我们将学习如何将个人兴趣转化为可持续的收入来源。我们将探讨传统职业路径的局限性&#xff0c;并介绍一种通过创造力和杠杆式工作来实现财务自由与生活满足感的新方法。课程的核心在于理解如何成为一个“价值创造者”&#xff0c;而不仅仅是出售时间。…...

HarmonyOS文件流操作指南:用ArkTS实现高效大文件传输与哈希校验

HarmonyOS文件流操作实战&#xff1a;ArkTS实现大文件传输与完整性校验 在移动应用开发中&#xff0c;文件操作是基础但至关重要的功能。当应用需要处理大型媒体文件、数据库备份或批量数据交换时&#xff0c;传统的文件IO方式往往力不从心。HarmonyOS提供的流式文件操作接口&a…...

从Bode到ADS:用‘策动点阻抗’判据,给你的电路稳定性加一道‘数学保险’

从Bode到ADS&#xff1a;用策动点阻抗判据为电路稳定性加一道数学保险 在射频电路设计中&#xff0c;稳定性分析就像给高速行驶的赛车安装防抱死系统——它不会直接提升性能&#xff0c;但能确保系统不会在关键时刻失控。传统K因子分析法如同简单的速度表&#xff0c;而策动点阻…...

科哥定制版Z-Image-Turbo体验:中文提示词友好,AI绘画小白也能玩转

科哥定制版Z-Image-Turbo体验&#xff1a;中文提示词友好&#xff0c;AI绘画小白也能玩转 1. 为什么选择科哥定制版Z-Image-Turbo 作为一名长期使用各类AI绘画工具的设计师&#xff0c;我发现科哥定制版的Z-Image-Turbo在中文提示词理解和生成效果上有着显著优势。这个版本基…...

2023最新版CCF期刊目录下载指南(附Python自动抓取脚本)

2023科研数据自动化&#xff1a;CCF期刊目录高效处理实战指南 科研工作者常面临海量期刊数据的筛选与分析难题。中国计算机学会(CCF)发布的推荐期刊目录作为计算机领域的重要参考标准&#xff0c;其结构化处理与深度分析能力直接影响研究效率。本文将突破传统PDF手工处理模式&a…...