select完成服务器并发

服务器

#include <myhead.h>#define PORT 4399 	//端口号
#define IP "192.168.0.191"//IP地址//键盘输入事件
int keybord_events(fd_set readfds);
//客户端交互事件
int cliRcvSnd_events(int , struct sockaddr_in*, fd_set *, int *);
//客户端连接事件
int cliConnect_events(int , struct sockaddr_in*, fd_set *, int *);int main(int argc, const char *argv[])
{//创建流式套接字int sfd = socket(AF_INET, SOCK_STREAM, 0);if(sfd < 0){ERR_MSG("socket");return -1;}printf("socket create success sfd=%d\n", sfd);//允许端口被快速复用int reuse = 1;if(setsockopt(sfd, SOL_SOCKET, SO_REUSEADDR, &reuse, sizeof(reuse)) < 0){ERR_MSG("setsockopt");return -1;}//填充地址信息结构体struct sockaddr_in sin;sin.sin_family = AF_INET;//必须填AF_INETsin.sin_port = htons(PORT);//端口号的网络字节序sin.sin_addr.s_addr = inet_addr(IP);//本机IP//绑定服务器的地址信息if(bind(sfd, (struct sockaddr*)&sin, sizeof(sin)) < 0){ERR_MSG("bind");return -1;}printf("bind success\n");//将套接字设置为被动监听状态if(listen(sfd, 128) < 0){ERR_MSG("listen");return -1;}printf("listen success\n");//创建一个读集合,一个操作集合fd_set readfds, tempfds;//清空集合FD_ZERO(&readfds);//将需要监测的文件描述符加入读集合FD_SET(0, &readfds);FD_SET(sfd, &readfds);int maxfd = sfd; 	//存储最大的文件描述符int s_res = -1;ssize_t res = -1;char buf[128] = "";struct sockaddr_in saveCin[1024]; 	//备份连接成功的客户端的地址信息,且用下标对应文件描述符while(1){tempfds = readfds;//执行多路复用函数s_res = select(maxfd+1, &tempfds, NULL, NULL, NULL);if(s_res < 0){ERR_MSG("select");return -1;}else if(0 == s_res){printf("time out...\n");break;}//此时代表select函数解除阻塞,集合中有文件描述符存在for(int i=0;i<=maxfd;i++){if(FD_ISSET(i, &tempfds) == 0)continue;//此时代表i所对应的文件描述符在集合中if(0 == i){keybord_events(readfds);}else if(sfd == i)//代表sfd在集合中{//	printf("触发客户端连接事件\n");cliConnect_events(sfd, saveCin, &readfds, &maxfd);}else{//	printf("触发客户端交互事件\n");cliRcvSnd_events(i, saveCin, &readfds, &maxfd);}}}if(close(sfd) < 0){ERR_MSG("close");return -1;}return 0;
}//键盘输入事件
int keybord_events(fd_set readfds)
{char buf[128] = "";int sndfd = -1;bzero(buf, sizeof(buf));int res = scanf("%d %s", &sndfd, buf);while(getchar() != 10);if(res != 2){printf("输入数据的格式错误 :fd string\n");return -1;}if(sndfd<=2 || FD_ISSET(sndfd, &readfds) == 0){printf("非法的文件描述符:sndfd=%d\n", sndfd);return -1;}if(send(sndfd, buf, sizeof(buf), 0) < 0){ERR_MSG("send");return -1;}printf("send success\n");return 0;
}//客户端连接事件
int cliConnect_events(int sfd, struct sockaddr_in saveCin[], fd_set *preadfds, int *pmaxfd)
{int newfd = -1;struct sockaddr_in cin;//存储客户端地址信息socklen_t addrlen = sizeof(cin); //真实的地址信息结构体的大小newfd = accept(sfd, (struct sockaddr*)&cin, &addrlen);if(newfd < 0){ERR_MSG("newfd");return -1;}printf("[%s:%d]客户端连接成功 newfd=%d\n",\inet_ntoa(cin.sin_addr), ntohs(cin.sin_port), newfd);saveCin[newfd] = cin; 	//将cin另存到newfd对应的下表位置FD_SET(newfd, preadfds); //将newfd添加到集合中*pmaxfd = *pmaxfd>newfd ? *pmaxfd:newfd; 	//更新maxfdreturn 0;
}//客户端交互事件
int cliRcvSnd_events(int fd, struct sockaddr_in* saveCin, fd_set *preadfds, int *pmaxfd)
{char buf[128] = "";//清空字符串bzero(buf, sizeof(buf));//接收ssize_t res = recv(fd, buf, sizeof(buf), 0);if(res < 0){ERR_MSG("recv");return -1;}else if(0 == res){printf("[%s:%d]客户端下线 newfd=%d\n",\inet_ntoa(saveCin[fd].sin_addr), ntohs(saveCin[fd].sin_port), fd);close(fd);//关闭文件描述符FD_CLR(fd, preadfds); //将文件描述符从集合中删除//由于删除的文件描述符可能是最大的文件描述符,所以要更新maxfdwhile(FD_ISSET(*pmaxfd, preadfds) == 0 && (*pmaxfd)-- >= 0);return 0;}printf("[%s:%d] newfd=%d:%s\n",\inet_ntoa(saveCin[fd].sin_addr), ntohs(saveCin[fd].sin_port), fd, buf);//发送信息strcat(buf, "*_*");if(send(fd, buf, sizeof(buf), 0) < 0){ERR_MSG("send");return -1;}printf("send success\n");return 0;
}

客户端

#include<myhead.h>#define PORT 4399             //服务器绑定的端口号
#define IP  "192.168.0.191"   //服务器绑定的IPint main(int argc, const char *argv[])
{//创建流式套接字 socketint cfd = socket(AF_INET, SOCK_STREAM, 0);if(cfd < 0){ERR_MSG("socket");return -1;}printf("socket create success cfd=%d\n", cfd);//绑定客户端的地址信息---》非必须绑定//当不手动绑定的时候,操作系统会自动给客户端绑定本机IP和随机端口。   //填充服务器的地址信息结构体给connect函数连接,//想连接哪个服务器,就填哪个服务器绑定的地址信息//真实的地址信息结构体根据地址族指定 AF_INET:man 7 ipstruct sockaddr_in sin;sin.sin_family      = AF_INET;      //必须填AF_INET;sin.sin_port        = htons(PORT);  //服务器绑定的端口号sin.sin_addr.s_addr = inet_addr(IP);//服务器绑定的IP//连接指定服务器 connectif(connect(cfd, (struct sockaddr*)&sin, sizeof(sin)) < 0){ERR_MSG("connect");return -1;}printf("connect success\n");//定义要监测的集合fd_set readfds,tempfds;FD_ZERO(&readfds);//将需要的文件描述符加入集合FD_SET(0,&readfds);FD_SET(cfd,&readfds);int s_res = -1;char buf[128] = "";ssize_t res = 0;while(1){tempfds=readfds;s_res = select(cfd+1, &tempfds, NULL, NULL, NULL);if(s_res < 0){ERR_MSG("selsct");	return -1;}else if(0 == s_res){printf("time out....\n");break;}//运行到此,则代表集合中有文件描述符准备就绪if(FD_ISSET(0, &tempfds)){//清空字符串bzero(buf, sizeof(buf));    fgets(buf, sizeof(buf), stdin);buf[strlen(buf)-1] = 0;//发送if(send(cfd, buf, sizeof(buf), 0) < 0){ERR_MSG("send");return -1;}printf("send success\n");}if(FD_ISSET(cfd, &tempfds)){bzero(buf, sizeof(buf));    //memset//接收res = recv(cfd, buf, sizeof(buf), 0);if(res < 0){ERR_MSG("recv");return -1;}else if(0 == res){printf("服务器下线 cfd=%d\n", cfd);break;}printf("cfd=%d : %s\n", cfd, buf);}}//关闭文件名描述符if(close(cfd) < 0){ERR_MSG("close");return -1;}return 0;
}

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/91749.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

计算机图像处理-中值滤波

非线性滤波 非线性滤波是利用原始图像跟模版之间的一种逻辑关系得到结果&#xff0c;常用的非线性滤波方法有中值滤波和高斯双边滤波&#xff0c;分别对应cv2.medianBlur(src, ksize)方法和cv2.bilateralFilter(src, d, sigmaColor, sigmaSpace[, dst[, borderType]])方法。 …

20分钟---Vue2->Vue3

Vue官网地址&#xff1a;gVue.js - The Progressive JavaScript Framework | Vue.js 选项式vs组合式 vue的两种风格&#xff0c;搬运官网源码&#xff1a; 选项式 API (Options API)​ 使用选项式 API&#xff0c;我们可以用包含多个选项的对象来描述组件的逻辑&#xff0c…

[题]欧拉函数 #欧拉函数

目录 欧拉函数一、用公式求代码 二、线性筛法求欧拉函数扩展欧拉定理 欧拉函数 AcWing 873. 欧拉函数 一、用公式求 定义&#xff1a;1 ~ N 中与 N 互质的数的个数被称为欧拉函数&#xff0c;记为ϕ(N)。 怎么求呢&#xff1f;&#xff1f; 有一个公式&#xff1a; N p1a1 X…

MASA MAUI iOS 文件下载与断点续传

文章目录 背景介绍方案及代码1、新建MAUI项目2、建立NSUrlSession会话连接3、使用NSUrlSessionDownloadTask 创建下载任务4、DidWriteData 监听下载5、DidFinishDownloading 完成下载6、CancelDownload (取消/暂停)下载7、ResumeDownload 恢复下载8、杀死进程-恢复下载 效果图总…

Python 小爬虫入门 -- 爬取专栏文章标题保存到 CSV 文件中

爬取专栏文章标题保存到 CSV 文件中目标分析网页代码及理解代码段一代码段二成果展示爬取专栏文章标题保存到 CSV 文件中 目标 从一个网页上抓取数据,并保存到一个 CSV 文件中。 具体是爬取 微机系统与接口上机实验_TD PITE型 专栏里的所有 文章标题 并 保存到 csv 文件 中…

GitHub配置SSH key

GitHub配置SSH key Git配置信息并生成密钥 设置用户名和密码 设置用户名 git config --global user.name "用户名" 设置邮箱 git confir --global user.email "邮箱" 生成密钥 ssh-keygen -t rsa -C "邮箱" 查看密钥 到密钥所保存的位置 复…

嵌入式Linux应用开发-第十四章查询方式的按键驱动程序

嵌入式Linux应用开发-第十四章查询方式的按键驱动程序 第十四章 查询方式的按键驱动程序_编写框架14.1 LED驱动回顾14.2 按键驱动编写思路14.3 编程&#xff1a;先写框架14.3.1 把按键的操作抽象出一个button_operations结构体14.3.2 驱动程序的上层&#xff1a;file_operation…

(高阶) Redis 7 第16讲 预热/雪崩/击穿/穿透 缓存篇

面试题 什么是缓存预热/雪崩/击穿/穿透如何做缓存预热如何避免或减少缓存雪崩穿透和击穿的区别?穿透和击穿的解决方案出现缓存不一致时,有哪些修补方案缓存预热 理论 将需要的数据提前加载到缓存中,不需要用户使用的过程中进行数据回写。(比如秒杀活动数据等) 方案 1.…

吉力宝:智能科技鞋品牌步力宝引领传统产业创新思维

在现代经济环境下&#xff0c;市场经济下产品的竞争非常的激烈&#xff0c;如果没有营销&#xff0c;产品很可能不被大众认可&#xff0c;酒香也怕巷子深&#xff0c;许多传统产业不得不面临前所未有的挑战。而为了冲出这个“巷子”&#xff0c;许多企业需要采用创新思维&#…

NLP 03(LSTM)

一、LSTM LSTM (Long Short-Term Memory) 也称长短时记忆结构,它是传统RNN的变体,与经典RNN相比&#xff1a; 能够有效捕捉长序列之间的语义关联缓解梯度消失或爆炸现象 LSTM的结构更复杂,它的核心结构可以分为四个部分去解析: 遗忘门、输入门、细胞状态、输出门 LSTM内部结构…

MyBatisPlus(六)字段映射 @TableField

字段注解&#xff08;非主键&#xff09; TableField 用于映射对象的 属性 和表中的 字段 。 当 属性名 和 字段名 差异较大的时候&#xff0c;无法通过默认的映射关系对应起来&#xff0c;就需要指定 属性名 对应 的 字段名。 官网示例 代码实例 package com.example.web.…

【网络原理】初始网络,了解概念

文章目录 1. 网络通信1.1 局域网LAN1.2 广域网WAN 2. 基础概念2.1 IP2.2 端口号 3. 认识协议4. 五元组5. 协议分层5.1 分层的作用5.2 OSI七层模型5.3 TCP/IP五层&#xff08;四层&#xff09;模型 6. 封装和分用 1. 网络通信 计算机与计算机之间是互相独立&#xff0c;是独立模…

【小沐学前端】Node.js实现UDP和Protobuf 通信(protobuf.js)

文章目录 1、简介1.1 node1.2 Protobuf 2、下载和安装2.1 node2.2 Protobuf 3、node 代码示例3.1 HTTP3.2 UDP单播3.4 UDP广播 4、Protobuf 代码示例4.1 例子:awesome.proto 结语 1、简介 1.1 node Node.js 是一个开源的、跨平台的 JavaScript 运行时环境。 Node.js 是一个开源…

Leetcode---364场周赛

题目列表 2864. 最大二进制奇数 2865. 美丽塔 I 2866. 美丽塔 II 2867. 统计树中的合法路径数目 一、最大二进制奇数 这题只要你对二进制有了解(学编程的不会不了解二进制吧)&#xff0c;应该问题不大&#xff0c;这题要求最大奇数&#xff0c;1.奇数&#xff1a;只要保证…

数据结构 | 二叉树

基本形状 可参照 数据结构&#xff1a;树(Tree)【详解】_数据结构 树_UniqueUnit的博客-CSDN博客 二叉树的性质 三种顺序遍历

区块链实验室(26) - 区块链期刊Blockchain: Research and Applications

Elsevier出版物“Blockchain: Research and Applications”是浙江大学编审的期刊。该期刊自2020年创刊&#xff0c;并出版第1卷。每年出版4期&#xff0c;最新期是第4卷第3期(2023年9月)。 目前没有官方的IF&#xff0c;Elsevier的引用因子Citescore是6.4。 虽然是新刊&#xf…

Android studio升级Giraffe | 2022.3.1 Patch 1踩坑

这里写自定义目录标题 not "opens java.io" to unnamed module错误报错信息解决 superclass access check failed: class butterknife.compiler.ButterKnifeProcessor$RScanner报错报错信息解决 Android studio升级Giraffe | 2022.3.1 Patch 1后&#xff0c;出现项目…

ElementUI之CUD+表单验证

目录 前言&#xff1a; 增删改查 表单验证 前言&#xff1a; 继上篇博客来写我们的增删改以及表单验证 增删改查 首先先定义接口 数据样式&#xff0c;我们可以去elementUI官网去copy我们喜欢的样式 <!-- 编辑窗体 --><el-dialog :title"title" :visib…

MT8385 Android AB分区系统升级(命令模式)

AB系统分区升级使用的是update_engine,RecoverySystem 只适用于单分区的系统升级 1.解压开update.zip 可以查看到palyload的属性 2.使用ADB命令update_engine_client即可对AB分区进行升级 使用adb shell 命令进行升级 update_engine_client --payload xxx --update --hea…

Qt扩展-QCustomPlot绘图基础概述

QCustomPlot绘图基础概述 一、概述二、改变外观1. Graph 类型2. Axis 坐标轴3. 网格 三、案例1. 简单布局两个图2. 绘图与多个轴和更先进的样式3. 绘制日期和时间数据 四、其他Graph&#xff1a;曲线&#xff0c;条形图&#xff0c;统计框图&#xff0c;… 一、概述 本教程使用…