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如…...
变量 varablie 声明- Rust 变量 let mut 声明与 C/C++ 变量声明对比分析
一、变量声明设计:let 与 mut 的哲学解析 Rust 采用 let 声明变量并通过 mut 显式标记可变性,这种设计体现了语言的核心哲学。以下是深度解析: 1.1 设计理念剖析 安全优先原则:默认不可变强制开发者明确声明意图 let x 5; …...
【SpringBoot】100、SpringBoot中使用自定义注解+AOP实现参数自动解密
在实际项目中,用户注册、登录、修改密码等操作,都涉及到参数传输安全问题。所以我们需要在前端对账户、密码等敏感信息加密传输,在后端接收到数据后能自动解密。 1、引入依赖 <dependency><groupId>org.springframework.boot</groupId><artifactId...
CMake基础:构建流程详解
目录 1.CMake构建过程的基本流程 2.CMake构建的具体步骤 2.1.创建构建目录 2.2.使用 CMake 生成构建文件 2.3.编译和构建 2.4.清理构建文件 2.5.重新配置和构建 3.跨平台构建示例 4.工具链与交叉编译 5.CMake构建后的项目结构解析 5.1.CMake构建后的目录结构 5.2.构…...
oracle与MySQL数据库之间数据同步的技术要点
Oracle与MySQL数据库之间的数据同步是一个涉及多个技术要点的复杂任务。由于Oracle和MySQL的架构差异,它们的数据同步要求既要保持数据的准确性和一致性,又要处理好性能问题。以下是一些主要的技术要点: 数据结构差异 数据类型差异ÿ…...
LLM基础1_语言模型如何处理文本
基于GitHub项目:https://github.com/datawhalechina/llms-from-scratch-cn 工具介绍 tiktoken:OpenAI开发的专业"分词器" torch:Facebook开发的强力计算引擎,相当于超级计算器 理解词嵌入:给词语画"…...
自然语言处理——Transformer
自然语言处理——Transformer 自注意力机制多头注意力机制Transformer 虽然循环神经网络可以对具有序列特性的数据非常有效,它能挖掘数据中的时序信息以及语义信息,但是它有一个很大的缺陷——很难并行化。 我们可以考虑用CNN来替代RNN,但是…...
【Go语言基础【12】】指针:声明、取地址、解引用
文章目录 零、概述:指针 vs. 引用(类比其他语言)一、指针基础概念二、指针声明与初始化三、指针操作符1. &:取地址(拿到内存地址)2. *:解引用(拿到值) 四、空指针&am…...
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…...
LOOI机器人的技术实现解析:从手势识别到边缘检测
LOOI机器人作为一款创新的AI硬件产品,通过将智能手机转变为具有情感交互能力的桌面机器人,展示了前沿AI技术与传统硬件设计的完美结合。作为AI与玩具领域的专家,我将全面解析LOOI的技术实现架构,特别是其手势识别、物体识别和环境…...
webpack面试题
面试题:webpack介绍和简单使用 一、webpack(模块化打包工具)1. webpack是把项目当作一个整体,通过给定的一个主文件,webpack将从这个主文件开始找到你项目当中的所有依赖文件,使用loaders来处理它们&#x…...
