10.1select并发服务器以及客户端
服务器:
#include<myhead.h>//do-while只是为了不让花括号单独存在,并不循环
#define ERR_MSG(msg) do{\fprintf(stderr,"%d:",__LINE__);\perror(msg);\
}while(0);#define PORT 8888//端口号1024-49151
#define IP "192.168.2.54"//本机IP,终端输入ifconfig可得int main(int argc, const char *argv[])
{//创建流式套接字 socketint sfd = socket(AF_INET,SOCK_STREAM,0);if(sfd<0){//printf("%d:",__LINE__);//perror("socket error");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_INETsin.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,tmpfds;//将文件描述符集合清空FD_ZERO(&readfds);//将文件描述符放入集合之中FD_SET(sfd,&readfds);FD_SET(0, &readfds);int maxfd = sfd;int res;char buf[128] = "";struct sockaddr_in cin; //存储客户端的地址信息socklen_t addrlen = sizeof(cin); //真实的地址信息结构体的大小//获取一个已经完成的客户端信息,生成一个新的文件描述符 acceptint newfd;struct sockaddr_in saveCin[1024]; //备份连接成功的客户端的地址信息,用下标来对应地址信息 while(1){tmpfds = readfds;//调用select函数res = select(maxfd+1,&tmpfds, NULL, NULL, NULL);if(res < 0){ERR_MSG("select error");break;}else if(0 == res){printf("time out\n");break;}else{for(int i=0; i<=maxfd; i++){if(0==FD_ISSET(i, &tmpfds)){continue;}else if(-1==FD_ISSET(i, &tmpfds)){ERR_MSG("FD_ISSET error");break;}if(0==i){//终端输入printf("从终端读取成功::");fgets(buf,sizeof(buf),stdin);buf[strlen(buf)-1] = 0;printf("%s\n",buf);}else if(sfd == i){if((newfd=accept(sfd,(struct sockaddr*)&cin,&addrlen))<0){ERR_MSG("accept");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, &readfds);//更新maxfdmaxfd = maxfd>newfd?maxfd:newfd;}else{if(FD_ISSET(i, &readfds)){//清空字符串bzero(buf,sizeof(buf)); //memset//接收res = recv(i, 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[i].sin_addr),\ntohs(saveCin[i].sin_port),i);//将文件描述符从集合中踢出FD_CLR(i, &readfds);//由于踢出的文件描述符可能是最大文件描述符,更新maxfd/* for(; maxfd>=0; maxfd--){if(FD_ISSET(maxfd, &readfds)){break;}} */while(FD_ISSET(maxfd, &readfds)==0 && maxfd-->=0);//关闭文件描述符close(i);continue;}printf("[%s:%d]客户端消息 newfd=%d:%s\n",\inet_ntoa(saveCin[i].sin_addr),\ntohs(saveCin[i].sin_port),i,buf); //发送strcat(buf,">_<");if(send(i,buf,strlen(buf),0)<0){ERR_MSG("send");return -1;}printf("send success\n"); } }}
/*//如果是终端输入就绪if(FD_ISSET(0,&tmpfds)){printf("从终端读取成功::");fgets(buf,sizeof(buf),stdin);buf[strlen(buf)-1] = 0;printf("%s\n",buf);}//如果是客户端连接就绪if(FD_ISSET(sfd,&tmpfds)){if((newfd=accept(sfd,(struct sockaddr*)&cin,&addrlen))<0){ERR_MSG("accept");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, &readfds);//更新maxfdmaxfd = maxfd>newfd?maxfd:newfd;}for(int i=4; i<=maxfd; i++){if(FD_ISSET(i, &readfds)){//清空字符串bzero(buf,sizeof(buf)); //memset//接收res = recv(i, 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[i].sin_addr),\ntohs(saveCin[i].sin_port),i);//将文件描述符从集合中踢出FD_CLR(i, &readfds);//由于踢出的文件描述符可能是最大文件描述符,更新maxfdfor(; maxfd>=0; maxfd--){if(FD_ISSET(maxfd, &readfds)){break;}} while(FD_ISSET(maxfd, &readfds)==0 && maxfd-->=0);//关闭文件描述符close(i);continue;}printf("[%s:%d]客户端消息 newfd=%d:%s\n",\inet_ntoa(saveCin[i].sin_addr),\ntohs(saveCin[i].sin_port),i,buf); //发送strcat(buf,">_<");if(send(i,buf,strlen(buf),0)<0){ERR_MSG("send");return -1;}printf("send success\n"); }}*/}}//关闭文件描述符close(newfd);if(close(sfd)<0){ERR_MSG("close");return -1;}return 0;
}
服务器:
#include<myhead.h>//do-while只是为了不让花括号单独存在,并不循环
#define ERR_MSG(msg) do{\fprintf(stderr,"%d:",__LINE__);\perror(msg);\
}while(0);#define PORT 8888//端口号1024-49151
#define IP "192.168.2.54"//本机IP,终端输入ifconfig可得int main(int argc, const char *argv[])
{//创建流式套接字 socketint cfd = socket(AF_INET,SOCK_STREAM,0);if(cfd<0){//printf("%d:",__LINE__);//perror("socket error");ERR_MSG("socket");return -1;}printf("socket create success sfd=%d\n",cfd);//填充服务器的地址信息结构体给connect函数连接//相连接哪个服务器就输入哪个服务器的地址信息//真是的地址信息结构体根据地址族制定 AF_INET:man 7 ipstruct sockaddr_in sin;sin.sin_family = AF_INET;//必须填AF_INETsin.sin_port = htons(PORT);//服务器绑定的端口号的网络字节序sin.sin_addr.s_addr = inet_addr(IP);//服务器绑定的IPsocklen_t addrlen = sizeof(sin);//连接指定服务器 connectif(connect(cfd,(struct sockaddr*)&sin,addrlen)<0){ERR_MSG("connect");return -1;}char buf[128] = "";ssize_t res = 0;//定义文件描述符集合fd_set readfds,tmpfds;//初始化集合FD_ZERO(&readfds);//把cfd加入集合FD_SET(cfd, &readfds);//把标准输入加入集合FD_SET(0, &readfds);int ret = -1;while(1){tmpfds = readfds;ret = select(cfd+1, &tmpfds, NULL, NULL, NULL);if(ret<0){ERR_MSG("select error");break;}else if(0 == ret){printf("time out\n");break;}else{if(FD_ISSET(0, &tmpfds)){//说明有来自终端的输入,需要发送//清空字符串bzero(buf,sizeof(buf)); //memsetprintf("请输入>> ");fgets(buf,sizeof(buf),stdin);buf[strlen(buf)-1] = 0;//发送strcat(buf,">_<");if(send(cfd,buf,strlen(buf),0)<0){ERR_MSG("send");return -1;}printf("send success\n");}if(FD_ISSET(cfd, &tmpfds)){//套接字文件的接收缓冲区有数据,需要接收//说明有来自终端的输入,需要发送//清空字符串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("[%s:%d]服务器下线 cfd=%d\n",\inet_ntoa(sin.sin_addr),\ntohs(sin.sin_port),cfd);break;}printf("[%s:%d]服务器消息 cfd=%d:%s\n",\inet_ntoa(sin.sin_addr),\ntohs(sin.sin_port),cfd,buf);}}}/*while(1){//清空字符串bzero(buf,sizeof(buf)); //memsetprintf("请输入>> ");fgets(buf,sizeof(buf),stdin);buf[strlen(buf)-1] = 0;//发送strcat(buf,">_<");if(send(cfd,buf,strlen(buf),0)<0){ERR_MSG("send");return -1;}printf("send success\n");//接收res = recv(cfd, buf, sizeof(buf) ,0);if(res<0){ERR_MSG("recv");return -1;}else if(0==res){printf("[%s:%d]服务器下线 cfd=%d\n",\inet_ntoa(sin.sin_addr),\ntohs(sin.sin_port),cfd);break;}printf("[%s:%d]服务器消息 cfd=%d:%s\n",\inet_ntoa(sin.sin_addr),\ntohs(sin.sin_port),cfd,buf); }
*///关闭文件描述符//close(newfd);if(close(cfd)<0){ERR_MSG("close");return -1;}return 0;
}
效果:

相关文章:
10.1select并发服务器以及客户端
服务器: #include<myhead.h>//do-while只是为了不让花括号单独存在,并不循环 #define ERR_MSG(msg) do{\fprintf(stderr,"%d:",__LINE__);\perror(msg);\ }while(0);#define PORT 8888//端口号1024-49151 #define IP "192.168.2.5…...
几个好用的测试HTTP请求的网站
Reqres (https://reqres.in):Reqres提供了一个模拟的REST API,您可以使用它来测试POST、GET、PUT等HTTP请求,并获得相应的响应结果。 JSONPlaceholder (https://jsonplaceholder.typicode.com):JSONPlaceholder是一个免费的JSON测…...
kafka简易搭建(windows环境)
1,下载 Apache Kafka 查找 kafka_2.13-3.2.1.tgz 2,java版本需要17以上 3,配置server.properties的log.dirs目录、zookeeper.properties 的dataDir目录 windows反斜杠地址 4,启动 cd D:\app\kafka_2.13-3.2.1 .\bin\window…...
毕业设计选题uniapp+springboot新闻资讯小程序源码 开题 lw 调试
💕💕作者:计算机源码社 💕💕个人简介:本人七年开发经验,擅长Java、Python、PHP、.NET、微信小程序、爬虫、大数据等,大家有这一块的问题可以一起交流! 💕&…...
Linux系统编程基础:进程控制
文章目录 一.子进程的创建操作系统内核视角下的父子进程存在形式验证子进程对父进程数据的写时拷贝 二.进程等待进程非阻塞等待示例: 三.进程替换内核视角下的进程替换过程:综合利用进程控制系统接口实现简单的shell进程 进程控制主要分为三个方面,分别是:子进程的创建,进程等待…...
选择和操作元素
上一篇文档我们介绍了DOM元素和DOM的获取;其实除了获取DOM,我们也可以去替换DOM元素中的文本 document.querySelector(.message).textContent "🎉Correct Number"● 除此之外,我们可以设置那个数字部分 document.que…...
消息中间件(二)——kafka
文章目录 Apache Kafka综述什么是消息系统?点对点消息类型发布-订阅消息类型 什么是Kafka?优点关键术语Kafka基本原理用例 Apache Kafka综述 在大数据中,会使用到大量的数据。面对这些海量的数据,我们一是需要做到能够收集这些数据…...
量化交易全流程(四)
本节目录 数据准备(数据源与数据库) CTA策略 数据源: 在进行量化分析的时候,最基础的工作是数据准备,即收集数据、清理数据、建立数据库。下面先讨论收集数据的来源,数据来源可分为两大类:免…...
idea 如何在命令行快速打开项目
背景 在命令行中从git仓库检出项目,如何在该命令行下快速用idea 打开当前项目,类似vscode 可以通过在项目根目录下执行 code . 快速打开当前项目。 步骤 以macos 为例 vim /usr/local/bin/idea 输入如下内容 #!/bin/sh open -na "IntelliJ IDE…...
YOLOV8-DET转ONNX和RKNN
目录 1. 前言 2.环境配置 (1) RK3588开发板Python环境 (2) PC转onnx和rknn的环境 3.PT模型转onnx 4. ONNX模型转RKNN 6.测试结果 1. 前言 yolov8就不介绍了,详细的请见YOLOV8详细对比,本文章注重实际的使用,从拿到yolov8的pt检测模型&…...
数量关系 --- 方程
目录 一、代入排除法 例题 练习 二、数字特性 例题 练习 整除特性 例题 倍数特性 普通倍数 因子倍数 比例倍数 例题 练习 三、方程法 例题 练习 四、 不定方程(组) 例题 练习 一、代入排除法 例题 素数:…...
【C语言 模拟实现strlen函数的三种方法】
C语言程序设计笔记---022 C语言之模拟实现strlen函数1、介绍strlen函数2、模拟strlen函数的三种方法2.1、计数器法模拟实现strlen函数2.2、递归法模拟实现strlen函数2.3、指针减指针法模拟实现strlen函数 3、结语 C语言之模拟实现strlen函数 前言: 通过C语言字符串…...
MySQL数据库与表管理《三国志》为例
在数据库管理中,一个典型的应用场景是游戏数据的存储和管理。以经典游戏《三国志》为例,该游戏具有多个角色、任务、装备等元素,如何有效地存储和管理这些数据就成为了一个问题。 本文将通过《三国志》的实例,详细解释如何在MySQL中进行数据库和表的管理。 文章目录 《三国…...
D. Jellyfish and Mex - DP
题面 分析: 题目最终需要达到MEX位0,也就是从最开始的MEX变成0后m的最小值,可以设 d p i dp_i dpi表示当前MEX为 i i i时,m的最小值,那么就可以根据前一个状态推出后一个状态,也就是假如当前MEX是 i i …...
奥斯卡·王尔德
奥斯卡王尔德 奥斯卡王尔德(Oscar Wilde,1854年10月16日—1900年11月30日),出生于爱尔兰都柏林,19世纪英国(准确来讲是爱尔兰,但是当时由英国统治)最伟大的作家与艺术家之一…...
IDEA常用快捷键大全
整理了一些IDEA开发常用的快捷键: 快捷键组合实现效果psvm Tab键 / main Tab键public static void main(String[] args)sout Tab键System.out.println()Ctrl X删除当前行Ctrl D复制当前行AltInsert(或右键Generate)生成代码(如get,set方法,构造函数等)CtrlAltT…...
Java之多线程的综合练习二
练习六:多线程统计并求最大值 需求: 在上一题基础上继续完成如下需求: 每次抽的过程中,不打印,抽完时一次性打印(随机) 在此次抽奖过程中,抽奖箱1总共产生了6个奖项。 分别为:10,20,100,50…...
selenium下载安装 -- 使用谷歌驱动碰到的问题
安装教程参考: http://c.biancheng.net/python_spider/selenium.html 1. 谷歌浏览器和谷歌驱动版本要对应(但是最新版本谷歌对应的驱动是没有的,因此要下载谷歌历史其他版本): 谷歌浏览器历史版本下载: https://www.chromedownloads.net/chrome64win/谷歌浏览器驱动下载: http:…...
开放式耳机怎么选择、300之内最好的耳机推荐
开放式耳机凭借不入耳、不伤耳、安全更舒适的佩戴体验,得到了越来越多音乐爱好者和专业人士的青睐。开放式耳机不需要插入耳道,在佩戴时可以更加自然和轻松,减少了长时间佩戴引起的不适感,而且不会完全隔绝外界声音,用…...
git密码提交切换SSH提交
git保存密码 每次登录都要输入密码是显示繁琐,好在git提供了保存密码的功能。 在本地工程文件夹下,.git目录,保存以下配置。 [credential] helper store或者 在git bash命令行,执行命令 git config credential.helper store如…...
大数据学习栈记——Neo4j的安装与使用
本文介绍图数据库Neofj的安装与使用,操作系统:Ubuntu24.04,Neofj版本:2025.04.0。 Apt安装 Neofj可以进行官网安装:Neo4j Deployment Center - Graph Database & Analytics 我这里安装是添加软件源的方法 最新版…...
Android Wi-Fi 连接失败日志分析
1. Android wifi 关键日志总结 (1) Wi-Fi 断开 (CTRL-EVENT-DISCONNECTED reason3) 日志相关部分: 06-05 10:48:40.987 943 943 I wpa_supplicant: wlan0: CTRL-EVENT-DISCONNECTED bssid44:9b:c1:57:a8:90 reason3 locally_generated1解析: CTR…...
装饰模式(Decorator Pattern)重构java邮件发奖系统实战
前言 现在我们有个如下的需求,设计一个邮件发奖的小系统, 需求 1.数据验证 → 2. 敏感信息加密 → 3. 日志记录 → 4. 实际发送邮件 装饰器模式(Decorator Pattern)允许向一个现有的对象添加新的功能,同时又不改变其…...
Cursor实现用excel数据填充word模版的方法
cursor主页:https://www.cursor.com/ 任务目标:把excel格式的数据里的单元格,按照某一个固定模版填充到word中 文章目录 注意事项逐步生成程序1. 确定格式2. 调试程序 注意事项 直接给一个excel文件和最终呈现的word文件的示例,…...
C++初阶-list的底层
目录 1.std::list实现的所有代码 2.list的简单介绍 2.1实现list的类 2.2_list_iterator的实现 2.2.1_list_iterator实现的原因和好处 2.2.2_list_iterator实现 2.3_list_node的实现 2.3.1. 避免递归的模板依赖 2.3.2. 内存布局一致性 2.3.3. 类型安全的替代方案 2.3.…...
2025年能源电力系统与流体力学国际会议 (EPSFD 2025)
2025年能源电力系统与流体力学国际会议(EPSFD 2025)将于本年度在美丽的杭州盛大召开。作为全球能源、电力系统以及流体力学领域的顶级盛会,EPSFD 2025旨在为来自世界各地的科学家、工程师和研究人员提供一个展示最新研究成果、分享实践经验及…...
听写流程自动化实践,轻量级教育辅助
随着智能教育工具的发展,越来越多的传统学习方式正在被数字化、自动化所优化。听写作为语文、英语等学科中重要的基础训练形式,也迎来了更高效的解决方案。 这是一款轻量但功能强大的听写辅助工具。它是基于本地词库与可选在线语音引擎构建,…...
初探Service服务发现机制
1.Service简介 Service是将运行在一组Pod上的应用程序发布为网络服务的抽象方法。 主要功能:服务发现和负载均衡。 Service类型的包括ClusterIP类型、NodePort类型、LoadBalancer类型、ExternalName类型 2.Endpoints简介 Endpoints是一种Kubernetes资源…...
基于SpringBoot在线拍卖系统的设计和实现
摘 要 随着社会的发展,社会的各行各业都在利用信息化时代的优势。计算机的优势和普及使得各种信息系统的开发成为必需。 在线拍卖系统,主要的模块包括管理员;首页、个人中心、用户管理、商品类型管理、拍卖商品管理、历史竞拍管理、竞拍订单…...
JS手写代码篇----使用Promise封装AJAX请求
15、使用Promise封装AJAX请求 promise就有reject和resolve了,就不必写成功和失败的回调函数了 const BASEURL ./手写ajax/test.jsonfunction promiseAjax() {return new Promise((resolve, reject) > {const xhr new XMLHttpRequest();xhr.open("get&quo…...
