select实现服务器并发

select的TCP服务器代码

#include <stdio.h>
#include <unistd.h>
#include <string.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <arpa/inet.h>
#include <netinet/in.h>
#include <sys/select.h>
#include <sys/time.h>#define ERR_MSG(msg)  do{\fprintf(stderr, "__%d__:", __LINE__); \perror(msg);\
}while(0)#define PORT 8888               //端口号,范围1024~49151
#define IP  "192.168.43.233"   //本机IP,ifconfigint keybord_events(fd_set readfds);
int cliConnect_events(int, struct sockaddr_in*, fd_set *, int *);
int cliRcvSnd_events(int, struct sockaddr_in*, fd_set *, int* );int main(int argc, const char *argv[])
{//创建流式套接字 socketint 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;}printf("允许端口快速的被复用成功\n");//填充地址信息结构体给bind函数绑定,//真实的地址信息结构体根据地址族指定 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//绑定服务器的地址信息---> 必须绑定 bindif(bind(sfd, (struct sockaddr*)&sin, sizeof(sin)) < 0){ERR_MSG("bind");return -1;}printf("bind success\n");//将套接字设置为被动监听状态 listenif(listen(sfd, 128) < 0){ERR_MSG("listen");return -1;}printf("listen success\n");//创建一个读集合fd_set readfds, tempfds;//fd_set 本质上是一个结构体,结构体中有一个整形数组。//若不清空,则会存有随机值,可能会随机到有效的,但是不需要监测的文件描述符//清空集合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;//执行IO多路复用函数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;}printf("__%d__\n", __LINE__);//能运行到当前位置,则代表select函数解除阻塞,即代表集合中有文件描述符准备就绪//此时集合中会只剩下产生事件的文件描述符,例如://0号准备就绪,则集合中会只剩下0号//sfd准备就绪,则集合中会只剩下sfd//0和sfd均准备就绪,则集合中会剩下0和sfd;//只需要判断集合中剩下哪个文件描述符,走对应处理函数即可;for(int i=0; i<=maxfd; i++){if(FD_ISSET(i, &tempfds) == 0)continue;//能运行到当前位置,则说明i所代表的文件描述符在集合中if(0 == i)          //0在集合中{printf("触发键盘输入事件\n");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));    //memset//接收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);   //将文件描述符从集合中剔除//由于剔除的文件描述符可能是最大文件描述符,所以要更新maxfd //从大往小判断,若在集合中,则该文件描述符就是最大的文件描述符/*for(; *pmaxfd>=0; *pmaxfd--){if(FD_ISSET(*pmaxfd, preadfds))break;}*/while(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;
}

 

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

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

相关文章

QChart使用说明

一.使用说明 Qt官网例程&#xff1a;https://doc.qt.io/qt-5/qtcharts-examples.html QChart&#xff1a;用于管理图表中的线、图例和轴的图形表示。可以简单理解为是一个画布。QChartView&#xff1a;视图组件&#xff0c;无法单独进行显示&#xff0c;需要依附其他组件进行…

SpringBoot的error用全局异常去处理

记录一下使用SpringBoot2.0.5的error用全局异常去处理 在使用springboot时&#xff0c;当访问的http地址或者说是请求地址输错后&#xff0c;会返回一个页面&#xff0c;如下&#xff1a; 这是因为请求的地址不存在&#xff0c;默认会显示error页面 但我们实际需要一个接口&a…

卷积神经网络的发展历史-VGG

VGG的产生 2014 年&#xff0c;Simonyan和Zisserman提出了VGG系列模型&#xff08;包括VGG-11/VGG-13/VGG-16/VGG-19&#xff09;&#xff0c;并在当年的ImageNet Challenge上作为分类任务第二名、定位&#xff08;Localization&#xff09;任务第一名的基础网络出现。 VGG的…

吃鸡达人必备!超实用干货激爽分享!

大家好&#xff01;作为一名专业吃鸡行家&#xff0c;今天我将为大家分享一些关于提高游戏战斗力和分享顶级游戏作战干货的秘诀&#xff0c;还有一些方便吃鸡作图、装备皮肤库存展示和查询的技巧&#xff01; 首先&#xff0c;让我们来介绍一些吃鸡作图工具推荐。无论是新手还是…

跨境电商系统对接-进口

一、跨境进口方式 1、一般贸易 指中国境内有进出口经营权的企业进行进出口贸易&#xff0c;货物到港后需要先清关&#xff08;办理海关申报、查验、征税、放行等手续&#xff09;&#xff0c;然后货主才能提货&#xff0c;一般贸易适合大批量进口商品&#xff0c;公司的鲜奶、…

ToBeWritten之改进威胁猎杀:自动化关键角色与成功沟通经验

也许每个人出生的时候都以为这世界都是为他一个人而存在的&#xff0c;当他发现自己错的时候&#xff0c;他便开始长大 少走了弯路&#xff0c;也就错过了风景&#xff0c;无论如何&#xff0c;感谢经历 转移发布平台通知&#xff1a;将不再在CSDN博客发布新文章&#xff0c;敬…

群晖搭建docker系统和办公服务2

首先先确认下我们的Office是否为VOL版&#xff0c;方法如下&#xff08;请您根据自身情况更改以下命令&#xff09;&#xff1a; 管理员身份运行命令提示符&#xff0c;输入 cd C:\Program Files\Microsoft Office\Office16 切换目录 &#xff08;这里请根据您自己的Office版本…

MySQL8 间隙锁在11种情况下的锁持有情况分析

测试环境及相关必要知识 测试环境为mysql 8 版本 间隙锁&#xff08;Gap Lock&#xff09;&#xff1a;用于锁定索引范围之间的间隙&#xff0c;防止其他事务在此间隙中插入新记录。间隙锁主要用于防止幻读问题。 在可重复读的隔离级别下默认打开该锁机制&#xff0c;解决幻…

Dubbo3应用开发—Dubbo3注册中心(zookeeper、nacos、consul)的使用

Dubbo3注册中心的使用 zookeeper注册中心的使用 依赖引入 <dependency><groupId>org.apache.dubbo</groupId><artifactId>dubbo-dependencies-zookeeper-curator5</artifactId><version>${dubbo.version}</version><type>p…

Vue中如何进行分布式日志收集与日志分析(如ELK Stack)

在Vue中实现分布式日志收集与日志分析&#xff08;使用ELK Stack&#xff09; 日志收集和分析在现代应用程序中是至关重要的&#xff0c;它们可以帮助开发人员监视和诊断应用程序的行为&#xff0c;从而提高应用程序的稳定性和性能。ELK Stack&#xff08;Elasticsearch、Logs…

ping使用

使用shell ping一个网段 #!/bin/shfor ib in $(seq 1 254); doip"192.168.1.$ib"(if ping -c3 "$ip" >> 1.txt; thenecho "$ip is alive"fi) &done wait在每次循环的最后&#xff0c;使用 & 将子 shell 放入后台执行&#xff0c…

基于FPGA的图像形态学腐蚀算法实现,包括tb测试文件和MATLAB辅助验证

目录 1.算法运行效果图预览 2.算法运行软件版本 3.部分核心程序 4.算法理论概述 5.算法完整程序工程 1.算法运行效果图预览 将FPGA的仿真结果导入到MATLAB,结果如下所示&#xff1a; 2.算法运行软件版本 vivado2019.2 matlab2022a 3.部分核心程序 timescale 1ns / 1ps…

【IR】按键

一、修改按键快速检查 1、修改ir.c已有按键功能快速验证: 如: 2、make customers 3、在根目录 cvte_build/resource/irkeycode下(这个是NEC协议的,其他协议也是一个道理,替换对应的tab就行了) remote_nec_irfac.tab是CVTE工厂遥控 remote_nec_ircus1.tab是客户遥控…

【prism】prism 框架代码

前言 这个是针对整个专栏的一个示例程序,应用了专栏里讲的一些知识点,他是一个小而美的Prism的框架代码,一个模板,方便大家去扩展一个prism工程。 下面是一些代码片段,最后我给出整个工程的下载链接~~~ 代码片段 主界面代码 <Window x:Class="PrismTest.Views…

数百个下载能够传播 Rootkit 的恶意 NPM 软件包

供应链安全公司 ReversingLabs 警告称&#xff0c;最近观察到的一次恶意活动依靠拼写错误来诱骗用户下载恶意 NPM 软件包&#xff0c;该软件包会通过 rootkit 感染他们的系统。 该恶意软件包名为“node-hide-console-windows”&#xff0c;旨在模仿 NPM 存储库上合法的“node-…

云服务器CVM_云主机_云计算服务器_弹性云服务器-腾讯云

腾讯云服务器CVM提供安全可靠的弹性计算服务&#xff0c;腾讯云明星级云服务器&#xff0c;弹性计算实时扩展或缩减计算资源&#xff0c;支持包年包月、按量计费和竞价实例计费模式&#xff0c;CVM提供多种CPU、内存、硬盘和带宽可以灵活调整的实例规格&#xff0c;提供9个9的数…

Python大数据之PySpark(七)SparkCore案例

文章目录 SparkCore案例PySpark实现SouGou统计分析 总结后记 SparkCore案例 PySpark实现SouGou统计分析 jieba分词&#xff1a; pip install jieba 从哪里下载pypi 三种分词模式 精确模式&#xff0c;试图将句子最精确地切开&#xff0c;适合文本分析&#xff1b;默认的方…

基于SpringBoot的植物健康系统

目录 前言 一、技术栈 二、系统功能介绍 系统首页 咨询专家 普通植物检查登记 珍贵植物检查登记 植物救治用料登记 植物救治材料管理 植物疾病案例管理 三、核心代码 1、登录模块 2、文件上传模块 3、代码封装 前言 随着信息技术在管理上越来越深入而广泛的应用&am…

Android之App跳转其他软件

文章目录 前言一、效果图二、实现步骤1.弹框xml(自己替换图标)2.弹框utils3.两个弹框动画4.封装方便调用5.调用6.长按事件方法7.跳转步骤8.复制utils 总结 前言 最近遇到一个需求&#xff0c;就是App内大面积需要长按复制并跳转指定App&#xff0c;没办法&#xff0c;只能埋头…

Hadoop设置hdfs全局指令

在终端进入用户个人环境变量配置文件 vim ~/.bashrc 然后添加如下内容 export PATH$PATH:/usr/local/hadoop/bin 添加到你的hadoop下载目录的bin目录为止就可以了 重新激活一下配置文件 source ~/.bashrc hdfs有专属于自己的文件存储目录,加上特殊的指令就可以箱终端一…