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如…...

UDP(Echoserver)
网络命令 Ping 命令 检测网络是否连通 使用方法: ping -c 次数 网址ping -c 3 www.baidu.comnetstat 命令 netstat 是一个用来查看网络状态的重要工具. 语法:netstat [选项] 功能:查看网络状态 常用选项: n 拒绝显示别名&#…...

【机器视觉】单目测距——运动结构恢复
ps:图是随便找的,为了凑个封面 前言 在前面对光流法进行进一步改进,希望将2D光流推广至3D场景流时,发现2D转3D过程中存在尺度歧义问题,需要补全摄像头拍摄图像中缺失的深度信息,否则解空间不收敛…...
数据链路层的主要功能是什么
数据链路层(OSI模型第2层)的核心功能是在相邻网络节点(如交换机、主机)间提供可靠的数据帧传输服务,主要职责包括: 🔑 核心功能详解: 帧封装与解封装 封装: 将网络层下发…...
【Java学习笔记】BigInteger 和 BigDecimal 类
BigInteger 和 BigDecimal 类 二者共有的常见方法 方法功能add加subtract减multiply乘divide除 注意点:传参类型必须是类对象 一、BigInteger 1. 作用:适合保存比较大的整型数 2. 使用说明 创建BigInteger对象 传入字符串 3. 代码示例 import j…...
CSS | transition 和 transform的用处和区别
省流总结: transform用于变换/变形,transition是动画控制器 transform 用来对元素进行变形,常见的操作如下,它是立即生效的样式变形属性。 旋转 rotate(角度deg)、平移 translateX(像素px)、缩放 scale(倍数)、倾斜 skewX(角度…...
【Android】Android 开发 ADB 常用指令
查看当前连接的设备 adb devices 连接设备 adb connect 设备IP 断开已连接的设备 adb disconnect 设备IP 安装应用 adb install 安装包的路径 卸载应用 adb uninstall 应用包名 查看已安装的应用包名 adb shell pm list packages 查看已安装的第三方应用包名 adb shell pm list…...
省略号和可变参数模板
本文主要介绍如何展开可变参数的参数包 1.C语言的va_list展开可变参数 #include <iostream> #include <cstdarg>void printNumbers(int count, ...) {// 声明va_list类型的变量va_list args;// 使用va_start将可变参数写入变量argsva_start(args, count);for (in…...

LabVIEW双光子成像系统技术
双光子成像技术的核心特性 双光子成像通过双低能量光子协同激发机制,展现出显著的技术优势: 深层组织穿透能力:适用于活体组织深度成像 高分辨率观测性能:满足微观结构的精细研究需求 低光毒性特点:减少对样本的损伤…...

恶补电源:1.电桥
一、元器件的选择 搜索并选择电桥,再multisim中选择FWB,就有各种型号的电桥: 电桥是用来干嘛的呢? 它是一个由四个二极管搭成的“桥梁”形状的电路,用来把交流电(AC)变成直流电(DC)。…...

前端开发者常用网站
Can I use网站:一个查询网页技术兼容性的网站 一个查询网页技术兼容性的网站Can I use:Can I use... Support tables for HTML5, CSS3, etc (查询浏览器对HTML5的支持情况) 权威网站:MDN JavaScript权威网站:JavaScript | MDN...