【网络编程】select实现服务器与客户端进行通信

1、运行1个服务器和2个客户端

实现效果:
        1、服务器和2个客户端互相聊天,服务器和客户端都需要使用select模型去实现
        2、服务器要监视2个客户端是否连接,2个客户端是否发来消息,以及服务器自己的标准输入流
        3、客户端要监视服务器是否发来消息,以及客户端自己的标准输入流
        4、在不开线程的情况下,实现互相聊天

小计:实现的结果是服务器能够同时和多个客户端进行通信,但是客户端之间不能进行通信

//Ser.c
#include <myhead.h>
#define SER_IP "192.168.2.7" // 服务器IP
#define SER_PORT 8888           // 服务器端口号int main(int argc, const char *argv[])
{// 1、创建用于监听的套接字int sfd = -1;sfd = socket(AF_INET, SOCK_STREAM, 0);// 参数1:表示使用的是ipv4的通信// 参数2:表示使用tcp通信类型// 参数3:表示前面已经特定了通信协议if (sfd == -1){perror("socket error");return -1;}printf("sfd = %d\n", sfd); // 3// 将端口号快速重用int reuse = 1;if (setsockopt(sfd, SOL_SOCKET, SO_REUSEADDR, &reuse, sizeof(reuse)) == -1){perror("setsockopt error");return -1;}printf("端口号快速重用成功\n");// 2、绑定ip地址和端口号// 2.1填充地址信息结构体struct sockaddr_in sin;sin.sin_family = AF_INET;                // 地址族sin.sin_port = htons(SER_PORT);          // 端口号sin.sin_addr.s_addr = inet_addr(SER_IP); // IP地址// 2.2绑定if (bind(sfd, (struct sockaddr *)&sin, sizeof(sin)) == -1){perror("bind error");return -1;}printf("bind success\n");// 3、启动监听,允许客户端连接if (listen(sfd, 128) == -1){perror("listen error");return -1;}printf("listen success\n");// 4、当有客户端发来连接请求后创建新的用于通信的套接字// 如果不想接收客户端地址信息结构体,则无需传入参数2和参数3// 如果想要获取客户端地址信息结构体,则需要传入相关参数struct sockaddr_in cin;          // 用于接收客户端地址信息结构体socklen_t socklen = sizeof(cin); // 用于接收客户端地址信息的大小int newfd = -1;                  // 新创建用于通信的套接字文件描述符char sbuf[128] = "";             // 从键盘上输入数据// 1、创建文件描述符容器fd_set readfds, tempfds;// 2、清空容器内容FD_ZERO(&readfds);// 3、将sfd和0号文件描述符放入容器中FD_SET(0, &readfds);FD_SET(sfd, &readfds);int maxfd = sfd;                  // 存放容器中最大的文件描述符的值struct sockaddr_in cin_arr[1024]; // 存放客户端对应的地址信息while (1){tempfds = readfds; // 将要检测的容器复制保存一份int res = select(maxfd + 1, &tempfds, NULL, NULL, NULL); // 阻塞等待集合中事件产生if (res == -1){perror("select error");return -1;}else if (res == 0){printf("time out\n");return -1;}// 遍历所有的容器中的文件描述符for (int i = 0; i <= maxfd; i++){// 判断当前的文件描述符是否在tempfds中,如果不在,直接下一个if (!FD_ISSET(i, &tempfds)){continue;}// 如果程序执行到此,说明检测的集合中的i文件描述符产生了事件if (i == sfd) // 表示sfd触发了事件{newfd = accept(sfd, (struct sockaddr *)&cin, &socklen);if (newfd == -1){perror("accept error");return -1;}printf("newfd = %d 您有新的客户已经上线\n", newfd);printf("客户端IP:%s, 端口号为:%d\n", inet_ntoa(cin.sin_addr), ntohs(cin.sin_port));// 将客户端文件描述符放入到集合中FD_SET(newfd, &readfds);cin_arr[newfd] = cin; // 将新的客户端地址信息放入容器// 更新一下maxfdif (newfd > maxfd){maxfd = newfd;}}else if (i == 0) // 表示有终端输入事件{// 从键盘输入数据fgets(sbuf, sizeof(sbuf), stdin);sbuf[strlen(sbuf) - 1] = 0;printf("触发了键盘输入事件:%s\n", sbuf);// 将消息发给每一个客户端for (int k = 4; k <= maxfd; k++){send(k, sbuf, strlen(sbuf), 0);}}else{// 5、通信套接字与客户端进行数据收发char rbuf[128] = "";// 清空容器bzero(rbuf, sizeof(rbuf));// 从套接字中读取数据int res = recv(i, rbuf, sizeof(rbuf), 0);if (res == 0){printf("客户端已经下线\n");// 6、关闭套接字close(i);// 将当前文件描述符从容器中移除FD_CLR(i, &readfds);// 更新maxfdfor (int j = maxfd; j >= 0; j--){if (FD_ISSET(j, &readfds)){maxfd = j;break;}}continue;}printf("[%s:%d] :%s\n",inet_ntoa(cin_arr[i].sin_addr), ntohs(cin_arr[i].sin_port), rbuf);// 将收到的消息加上其他字符回过去strcat(rbuf, "*_*");send(i, rbuf, strlen(rbuf), 0);}}}close(sfd);return 0;
}
//Cli.c
#include <myhead.h>
#define SER_IP "192.168.2.7" // 服务器IPint main(int argc, const char *argv[])
{if(argc != 2){printf("请输入正确的端口号\n");return -1;}// 1、创建服务器端套接字int cfd = -1;cfd = socket(AF_INET, SOCK_STREAM, 0);// 参数1:表示使用的是ipv4的通信// 参数2:表示使用tcp通信类型// 参数3:表示前面已经特定了通信协议if (cfd == -1){perror("socket error");return -1;}printf("sfd = %d\n", cfd); // 3// 将端口号快速重用int reuse = 1;if (setsockopt(cfd, SOL_SOCKET, SO_REUSEADDR, &reuse, sizeof(reuse)) == -1){perror("setsockopt error");return -1;}printf("端口号快速重用成功\n");// 2、绑定ip地址和端口号// 2.1填充地址信息结构体struct sockaddr_in sin;sin.sin_family = AF_INET;                // 地址族sin.sin_port = htons(8888);          // 端口号sin.sin_addr.s_addr = inet_addr(SER_IP); // IP地址// 4、当有客户端发来连接请求后创建新的用于通信的套接字// 如果不想接收客户端地址信息结构体,则无需传入参数2和参数3// 如果想要获取客户端地址信息结构体,则需要传入相关参数struct sockaddr_in cin;          // 用于接收客户端地址信息结构体socklen_t socklen = sizeof(cin); // 用于接收客户端地址信息的大小int newfd = -1;                  // 新创建用于通信的套接字文件描述符char sbuf[128] = "";             // 从键盘上输入数据// 1、创建文件描述符容器fd_set readfds, tempfds;// 2、清空容器内容FD_ZERO(&readfds);// 3、将sfd和0号文件描述符放入容器中FD_SET(0, &readfds);FD_SET(cfd, &readfds);int maxfd = cfd;                  // 存放容器中最大的文件描述符的值struct sockaddr_in cin_arr[1024]; // 存放客户端对应的地址信息//连接到服务器if(connect(cfd, (struct sockaddr *)&sin, sizeof(sin)) == -1){perror("connect error");return -1;}printf("成功连接到服务器\n");while (1){tempfds = readfds; // 将要检测的容器复制保存一份int res = select(maxfd + 1, &tempfds, NULL, NULL, NULL); // 阻塞等待集合中事件产生if (res == -1){perror("select error");return -1;}else if (res == 0){printf("time out\n");return -1;}// 遍历所有的容器中的文件描述符for (int i = 0; i <= maxfd; i++){// 判断当前的文件描述符是否在tempfds中,如果不在,直接下一个if (!FD_ISSET(i, &tempfds)){continue;}// 如果程序执行到此,说明检测的集合中的i文件描述符产生了事件if (i == cfd) // 表示cfd触发了事件{//收到了服务器发来的消息char buf[128] = "";bzero(buf,sizeof(buf));recv(cfd, buf, sizeof(buf), 0);printf("%s\n",buf);}else if (i == 0) // 表示有终端输入事件{// 从键盘输入数据fgets(sbuf, sizeof(sbuf), stdin);sbuf[strlen(sbuf) - 1] = 0;printf("触发了键盘输入事件:%s\n", sbuf);// 将消息发给服务器send(cfd, sbuf, sizeof(sbuf), 0);}}}close(cfd);return 0;
}

输出结果如下:

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

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

相关文章

定格精彩瞬间!详解六自由度技术原理及应用

在体育赛事中&#xff0c;观赏各项目的精彩瞬间&#xff0c;欣赏运动员的卓越表现是观众们最为关注的焦点。以体操跳马为例&#xff0c;运动员们全力助跑&#xff0c;然后奋力起跳、腾空&#xff0c;接着精准的推手和转体动作&#xff0c;最后稳稳落地&#xff0c;整个动作行云…

检测到目标URL存在http host头攻击漏洞

漏洞描述 修复措施 方法一&#xff1a; nginx 的 default_server 指令可以定义默认的 server 去处理一些没有匹配到 server_name 的请求&#xff0c;如果没有显式定义&#xff0c;则会选取第一个定义的 server 作为 default_server。 server { …

avue-crud 自定义搜索项 插槽

加上 -search 就可以自定义查询项了

【MongoDB】Java连接MongoDB

连接URI 连接 URI提供驱动程序用于连接到 MongoDB 部署的指令集。该指令集指示驱动程序应如何连接到 MongoDB&#xff0c;以及在连接时应如何运行。下图解释了示例连接 URI 的各个部分&#xff1a; 连接的URI 主要分为 以下四个部分 第一部分 连接协议 示例中使用的 连接到具有…

ant design pro 中用户的表单如何控制多个角色

ant design pro 如何去保存颜色ant design pro v6 如何做好角色管理ant design 的 tree 如何作为角色中的权限选择之一ant design 的 tree 如何作为角色中的权限选择之二ant design pro access.ts 是如何控制多角色的权限的 看上面的图片 当创建或编辑一个用户时&#xff0c;…

Mac文件需要分卷压缩怎么办 Mac上怎么解压分卷压缩的文件

在处理大型文件的传输和存储的时候&#xff0c;Mac用户常面临文件大小超过限制的问题。为了有效管理这些大文件&#xff0c;分卷压缩成为一种必不可少的解决方案。Mac文件需要分卷压缩怎么办&#xff1f;Mac上怎么解压分卷压缩的文件&#xff1f;本文将向你介绍如何使用BetterZ…

第R2周:LSTM-火灾温度预测

&#x1f368; 本文为&#x1f517;365天深度学习训练营 中的学习记录博客&#x1f356; 原作者&#xff1a;K同学啊 一、什么是LSTM 1.LSTM的本质 长短时记忆网络&#xff08;Long Short-Term Memory, LSTM&#xff09;的本质是一种特殊的循环神经网络&#xff08;Recurrent…

使用Go语言将PDF文件转换为Base64编码

使用 Go 语言将 Base64 编码转换为 PDF 文件-CSDN博客本文介绍了如何使用 Go 语言将 Base64 编码转换为 PDF 文件&#xff0c;并保存到指定路径。https://blog.csdn.net/qq_45519030/article/details/141225772 在现代编程中&#xff0c;数据转换和编码是常见的需求。本文将介绍…

SX_gitlab可视化操作c语言知识_17

gitlab可视化操作技巧: Merge into current branch直接将远程wjc_GNSS分支的数据拉下来同步到本机当前的分支代码&#xff0c;执行的是合并操作&#xff0c;即多的模块会添加到本地分支&#xff0c;有冲突的地方不行得rebase覆盖才行 修改完代码先暂存更改再在暂存区写入备注&a…

网络通信要素

网络介绍 定义&#xff1a;将具有独立功能的多台计算机通过通信线路和通信设备连接起来&#xff0c;在网络管理软件及网络通信协议下&#xff0c;实现资源共享和信息传递的虚拟平台。 学习网络的目的&#xff1a; 能够编写基于网络通信的软件或程序&#xff0c;通常来说就是网…

力扣面试经典算法150题:删除有序数组中的重复项 II

删除有序数组中的重复项 II 今天的题目是力扣面试经典150题中的数组的中等难度题: 删除有序数组中的重复项 II 题目链接&#xff1a;https://leetcode.cn/problems/remove-duplicates-from-sorted-array-ii/description/?envTypestudy-plan-v2&envIdtop-interview-150 题…

时间序列分析2|ARIMA模型|SARIMA模型

ARMA模型的定阶 自相关和偏自相关系数法 通过观察样本的自相关系数(ACF)和偏自相关系数(PACF)&#xff0c;进行大体的判断 模型定阶的经验方法 截尾&#xff1a; 最初的d阶样本(偏)自相关系数明显在2倍标准差范围外95%的(偏)自相关系数都落在2倍标准差的范围以内非零自相…

【论文阅读】通用的语义-几何表征的机器人操作

文章目录 1. 【2023CoRL】A Universal Semantic-Geometric Representation for Robotic Manipulation针对痛点和贡献引言模型框架思考不足之处 2. Leveraging Locality to Boost Sample Efficiency in Robotic Manipulation摘要和结论引言模型框架实验思考不足之处 1. 【2023Co…

ES6-ES13学习笔记

目录 初识ES6 变量声明 解构赋值 对象解构 ​编辑 数组解构 ​编辑模版字符串 字符串扩展 includes() repeat() startsWith() endsWith() 数值扩展 二进制和八进制表示法 &#xff08;Number.&#xff09;isFinite()与isNaN() Number.isInteger() Math.trunc …

Leetcode JAVA刷刷站(69)x的平方根

一、题目概述 二、思路方向 在Java中&#xff0c;计算一个非负整数x的算术平方根&#xff0c;并返回其整数部分&#xff0c;你可以使用二分查找法。这是因为平方根函数是单调递增的&#xff0c;所以我们可以利用二分查找在合理的时间复杂度内找到结果。 三、代码实现 public…

Matplotlib入门与进阶:数据可视化的强大工具

Matplotlib入门与进阶&#xff1a;数据可视化的强大工具 在当今数据驱动的世界中&#xff0c;数据可视化成为了数据分析的重要一环。数据可视化不仅能够帮助开发者理解和分析数据&#xff0c;还能使数据展示更具说服力。本文将详细介绍Python中的2D绘图库——Matplotlib。通过…

Python自准直仪双筒望远镜光学ABCD矩阵行为算法

&#x1f3af;要点 &#x1f3af;平面&#xff1b;曲面&#xff1b;圆柱面&#xff1b;非球面光&#xff0c;双凸透镜&#xff1b;90 度棱镜&#xff1b;分束立方体&#xff0c;双透镜棱&#xff1b;镜分光镜光线&#xff1b;横置隔膜&#xff1b;全内反射&#xff1b;多个分束…

作业08.21

服务器&#xff1a; #include <myhead.h>#define SER_PORT 6666 #define SER_IP "127.0.0.1"int find_client(int *client_arr, int len, int client) {for(int i0; i<len; i){if(client_arr[i] client){return i;}}return -1; }void remove_client(int *…

python爬虫--pyquery解析库整理

前言 欢迎来到我的博客 个人主页:北岭敲键盘的荒漠猫-CSDN博客 本文整理python的爬虫解析库pyquery的语法 简洁快速的整理&#xff0c;建议有前端基础的人看 pyquery解析原理 pyquery的原理就是拿到网站的前端源码后&#xff0c;我们根据我们需求信息所在的标签进行筛选。 选…

漏洞挖掘 | 记一次edusrc--轻松拿下中危信息泄露

1.前言 也是一次漏洞挖掘的思路分享 上次我们讲过了关于小程序方面的一些小思路&#xff0c;即关于抓包更改id号造成的一个信息泄露&#xff0c;但是在小程序上的信息泄露很难涉及到公民三要素这是一个痛点&#xff0c;今天就来分享一下一次edu挖掘时挖到的一个涉及公民三要素…