网络编程day05(IO多路复用)
今日任务:
TCP多路复用的客户端、服务端:
服务端代码:
#include <stdio.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <arpa/inet.h>
#include <netinet/in.h>
#include <unistd.h>
#include <string.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.125.2" //本机IP,ifconfigint keyboardEvents(void);
int cliconnectEvents(int sfd, struct sockaddr_in* pCin, fd_set *preadfds, int *pmaxfd);
int cliDealMsgEvnets(int newfd, struct sockaddr_in pCin[], fd_set *preadfds, int* pmaxfd);int main(int argc, const char *argv[])
{//创建流式套接字int 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); //端口号的网络字节序,1024~49151sin.sin_addr.s_addr = inet_addr(IP); //本机IP的网络字节序,ifconfig//绑定服务器的地址信息---》必须绑定if(bind(sfd, (struct sockaddr*)&sin, sizeof(sin)) < 0){ ERR_MSG("bind");return -1; } printf("bind success\n");//将套接字转换成被动监听状态if(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; //存储集合中最大的文件描述符struct sockaddr_in saveCin[1024-3]; //将客户端的信息另存char buf[128] = ""; ssize_t res = 0;int newfd = -1; int s_res = 0;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__);//能运行到当前位置,则代表集合中有文件描述符准备就绪//判断哪个文件描述符准备就绪,走对应处理函数即可//当函数解除阻塞后,集合中会只剩下产生事件的文件描述符;例如://0号准备就绪,则集合中只剩下0号//sfd准备就绪,则集合中只能下sfd;//0和sfd均准备就绪,则0和sfd均存在//所以只需要遍历集合中剩下哪个文件描述符,就代表哪个文件描述符准备就绪for(int i=0; i<=maxfd; i++) {if(FD_ISSET(i, &tempfds) == 0) //若i所代表的文件描述符不存在,则遍历下一个文件描述符continue;//能运行到当前位置,说明i所代表的文件描述符在集合中。//判断i所代表的文件描述符是什么(0, sfd , 其他newfd),走对应处理函数即可if(0 == i) //说明0在集合中{printf("触发键盘输入事件\n");keyboardEvents();}else if(sfd == i) //说明sfd在集合中{printf("触发客户端连接事件\n");cliconnectEvents(sfd, saveCin, &readfds, &maxfd);}else {printf("触发客户端交互事件\n");cliDealMsgEvnets(i, saveCin, &readfds, &maxfd);}}} //关闭套接字close(sfd);return 0;
}int cliDealMsgEvnets(int newfd, struct sockaddr_in pCin[], fd_set *preadfds, int* pmaxfd)
{ssize_t res = -1; char buf[128] = ""; //接收数据res = recv(newfd, buf, sizeof(buf), 0); if(res < 0){ ERR_MSG("recv");return -1; } else if(0 == res){ printf("[%s:%d] newfd=%d 客户端下线__%d__\n", \inet_ntoa(pCin[newfd-3].sin_addr), ntohs(pCin[newfd-3].sin_port), newfd, __LINE__);close(newfd); //关闭文件描述符FD_CLR(newfd, preadfds); //剔除该文件描述符//更新maxfd, 从当前最大的文件描述符开始判断是否在集合中//若在,则该文件描述符就是最大文件描述符for(; *pmaxfd>=0; *pmaxfd--)if(FD_ISSET(*pmaxfd, preadfds))break;//while(!FD_ISSET(*pmaxfd, preadfds) && *pmaxfd-->=0);return 0;} printf("[%s:%d] newfd=%d : %s __%d__\n", \inet_ntoa(pCin[newfd-3].sin_addr), ntohs(pCin[newfd-3].sin_port), newfd, buf, __LINE__);//发送数据strcat(buf, "*_*"); if(send(newfd, buf, sizeof(buf), 0) < 0){ ERR_MSG("send");return -1; } printf("send success\n");return 0;
}int cliconnectEvents(int sfd, struct sockaddr_in* pCin, fd_set *preadfds, int *pmaxfd)
{struct sockaddr_in cin; //存储客户端的地址信息socklen_t addrlen = sizeof(cin);int newfd ;newfd = accept(sfd, (struct sockaddr*)&cin, &addrlen);if(newfd < 0){ ERR_MSG("accept");return -1; } printf("[%s:%d] newfd=%d 客户端连接成功__%d__\n", \inet_ntoa(cin.sin_addr), ntohs(cin.sin_port), newfd, __LINE__);pCin[newfd-3] = cin; //将客户端信息另存FD_SET(newfd, preadfds); //将newfd添加到集合中*pmaxfd = *pmaxfd>newfd ? *pmaxfd:newfd; //更新maxfdreturn 0;
}int keyboardEvents(void)
{char buf[128] = ""; fgets(buf, sizeof(buf), stdin);buf[strlen(buf)-1] = 0;printf(":%s\n", buf);return 0;
}
客户端代码:
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <arpa/inet.h>
#include <unistd.h>
#include <sys/select.h>
//自定义报错提示
#define ERR_MSG(msg) do{\fprintf(stderr,"__%d__",__LINE__);\perror(msg);\
}while(0)
#define SER_PORT 8887
#define SER_IP "192.168.125.2"
/** function: TCP客户端* @param [ in] * @param [out] * @return */
int main(int argc, const char *argv[])
{//1.创建socket套接字,int cfd=socket(AF_INET,SOCK_STREAM,0);if(cfd<0){ERR_MSG("socket");return -1;}puts("socket create");//允许端口快速复用int reuse = 1;if(setsockopt(cfd, SOL_SOCKET, SO_REUSEADDR, &reuse, sizeof(reuse)) < 0){ERR_MSG("setsockopt");return -1;}printf("允许端口快速复用成功\n");//2.连接服务端connectstruct sockaddr_in addr;addr.sin_family=AF_INET;addr.sin_port=htons(SER_PORT);addr.sin_addr.s_addr=inet_addr(SER_IP);if(connect(cfd,(struct sockaddr*)&addr,sizeof(addr))<0){ERR_MSG("connect");return -1;}puts("connect success");//3.用多路复用实现实时的消息交流//3.1)创建集合,清空集合fd_set readfds,tem_readfds;FD_ZERO(&readfds);//3.2)添加需要使用的文件描述符FD_SET(0,&readfds);FD_SET(cfd,&readfds);//3.3)调用多路复用函数,阻塞char buf[128]="";while(1){tem_readfds=readfds;int sel_res=select(cfd+1,&tem_readfds,NULL,NULL,NULL);if(sel_res<0){ERR_MSG("select");return -1;}if(FD_ISSET(0,&tem_readfds)){//执行写操作;bzero(buf,sizeof(buf));printf("请输入>>>");fgets(buf,sizeof(buf),stdin);buf[strlen(buf)-1]='\0';if(strcmp(buf,"quit")==0)break;int send_res=send(cfd,buf,sizeof(buf),0);if(send_res<0){ERR_MSG("send");return -1;}puts("send success");}if(FD_ISSET(cfd,&tem_readfds)){//执行接受消息命令bzero(buf,sizeof(buf));int recv_res=recv(cfd,buf,sizeof(buf),0);if(recv_res<0){ERR_MSG("recv");return -1;}else if(recv_res==0){printf("socket peer has shutdown\n");break;}puts("recv success");printf("[%s:%d]:%s\n",SER_IP,SER_PORT,buf);}}//6.关闭close(cfd);return 0;
}
今日思维导图
相关文章:

网络编程day05(IO多路复用)
今日任务: TCP多路复用的客户端、服务端: 服务端代码: #include <stdio.h> #include <sys/types.h> #include <sys/socket.h> #include <arpa/inet.h> #include <netinet/in.h> #include <unistd.h> …...

人声分离网站,帮你快速提取视频中的人声和背景音乐
今天给大家带来一个可以分离人声的网站——音分轨,他运用人工智能算法可以将音频中的人声部分和音乐部分分离,使我们的视频制作过程可以更方便。 我们点击右下角“选择文件”上传一个音频,上传好音频后,人工智能就开始处理我们上传…...

计算机网络常见问题
1.谈一谈对OSI七层模型和TCP/IP四层模型的理解? 1.1.为什么要分层? 在计算机中网络是个复杂的系统,不同的网络与网络之间由于协议,设备,软件等各种原因在协调和通讯时容易产生各种各样的问题。例如:各物流…...

上PICO,沉浸式观看亚运直播,参与跨国界游戏竞技
备受瞩目的杭州第19届亚运会,将于9月23日正式开幕。据悉,这也是有史以来项目最多的一届亚运会,除部分传统奥运项目外,还包含武术、藤球、板球、克柔术、柔术等亚洲特色项目,以及霹雳舞、电子竞技等深受年轻人喜爱的新兴…...
无重复字符的最长子串 - 力扣(LeetCode)
3. 无重复字符的最长子串 - 力扣(LeetCode) 给定一个字符串 s ,请你找出其中不含有重复字符的 最长子串 的长度。 示例 1: 输入: s "abcabcbb" 输出: 3 解释: 因为无重复字符的最长子串是 "abc",所以其长…...
企业行政许可的种类有哪些?
从行政许可的性质、功能和适用条件的角度来说,大体可以划分为五类:普通许可、特许、认可、核准、登记。 1.普通许可 普通许可是一种允许符合特定条件的相对方行使某种权利的行为。在许多情况下,需要普通许可的活动都与国家安全、公共安全息…...

Flink--4、DateStream API(执行环境、源算子、基本转换算子)
星光下的赶路人star的个人主页 注意力的集中,意象的孤立绝缘,便是美感的态度的最大特点 文章目录 1、DataStream API1.1 执行环境(Execution Environment)1.1.1 创建执行环境 1.2 执行模式(Execution Mode)…...

#循循渐进学51单片机#指针基础与1602液晶的初步认识#not.11
1、把本节课的指针相关内容,反复学习3到5遍,彻底弄懂指针是怎么回事,即使是死记硬背也要记住,等到后边用的时候可以实现顿悟。学会指针,就是突破了C语言的一道壁垒。 2,1602所有的指令功能都应用一遍&#…...

Lua学习笔记:探究package
前言 本篇在讲什么 理解Lua的package 本篇需要什么 对Lua语法有简单认知 对C语法有简单认知 依赖Visual Studio工具 本篇的特色 具有全流程的图文教学 重实践,轻理论,快速上手 提供全流程的源码内容 ★提高阅读体验★ 👉 ♠ 一级…...

【面试经典150 | 双指针】三数之和
文章目录 写在前面Tag题目来源题目解读解题思路方法一:暴力枚举方法二:双指针 写在最后 写在前面 本专栏专注于分析与讲解【面试经典150】算法,两到三天更新一篇文章,欢迎催更…… 专栏内容以分析题目为主,并附带一些对…...
现代卷积网络实战系列3:PyTorch从零构建AlexNet训练MNIST数据集
1、AlexNet AlexNet提出了一下5点改进: 使用了Dropout,防止过拟合使用Relu作为激活函数,极大提高了特征提取效果使用MaxPooling池化进行特征降维,极大提高了特征提取效果首次使用GPU进行训练使用了LRN局部响应归一化(…...

Django系列:Django应用(app)的创建与配置
Django系列 Django应用(app)的创建与配置 作者:李俊才 (jcLee95):https://blog.csdn.net/qq_28550263 邮箱 :291148484163.com 本文地址:https://blog.csdn.net/qq_28550263/article…...
Linux查看程序和动态库依赖的动态库
一. 前言 在一些时候,我们需要知道一个程序或者动态库所依赖的动态库有哪些。比如,当我们运行一个程序的时候,发现可能会报错,提示找不到某个符号,这时我们就需要知道程序依赖了什么库,从而添加对应需要的动…...
vue3 无法使用pnpm安装依赖 或 Cannot find module preinstall.js
创建.npmrc文件在根目录 shamefully-hoisttrue auto-install-peerstrue strict-peer-dependenciesfalse删除 node_modules 和 pnpm-lock.yaml 文件 重新 pnpm i 就可以啦...

C/C++连接数据库,包含完整代码。
C/C连接数据库 本篇文章意在简洁明了的在linux环境下使用C/C连接远程数据库,并对数据库进行增删查改等操作。我所使用的环境是centos7,不要环境除环境配置外,代码是大同小异的。完整代码在最底部!!! 1.前…...

AUTOSAR词典:CAN驱动Mailbox配置技术要点全解析
AUTOSAR词典:CAN驱动Mailbox配置技术要点全解析 前言 首先,请问大家几个小小问题,你清楚: AUTOSAR框架下的CAN驱动关键词定义吗?是不是有些总是傻傻分不清楚呢?CAN驱动Mailbox配置过程中有哪些关键配置参…...

C语言 coding style
头文件 The #define Guard #define的保护文件的唯一性,防止被多重包含 格式 : <PROJECT>_< FILE>_H_ PROJECT : XS FILE : MV_CTR 头文件的包含顺序 C System FilesOther LibrariesUser LibraryConditional include 作用域 局部变量 -变量定义时需要…...
Python办公自动化之PDF
Python操作PDF 1、Python操作PDF概述2、批量拆分3、批量合并4、提取内容(文字)5、提取内容(表格)6、提取图片7、PDF添加水印8、加密与解密1、Python操作PDF概述 Python操作PDF主要有两个库:PyPDF2和pdfplumber PyPDF2是一个用于处理PDF文件的Python第三方库 官网文档参考:…...
【每日一题Day331】LC2560打家劫舍 IV | 二分查找 + 贪心
打家劫舍 IV【LC2560】 沿街有一排连续的房屋。每间房屋内都藏有一定的现金。现在有一位小偷计划从这些房屋中窃取现金。 由于相邻的房屋装有相互连通的防盗系统,所以小偷 不会窃取相邻的房屋 。 小偷的 窃取能力 定义为他在窃取过程中能从单间房屋中窃取的 最大金额…...

JVM 参数详解
GC有两种类型:Scavenge GC 和Full GC 1、Scavenge GC 一般情况下,当新对象生成,并且在Eden申请空间失败时,就会触发Scavenge GC,堆的Eden区域进行GC,清除非存活对象,并且把尚且存活的对象移动到…...
mongodb源码分析session执行handleRequest命令find过程
mongo/transport/service_state_machine.cpp已经分析startSession创建ASIOSession过程,并且验证connection是否超过限制ASIOSession和connection是循环接受客户端命令,把数据流转换成Message,状态转变流程是:State::Created 》 St…...
服务器硬防的应用场景都有哪些?
服务器硬防是指一种通过硬件设备层面的安全措施来防御服务器系统受到网络攻击的方式,避免服务器受到各种恶意攻击和网络威胁,那么,服务器硬防通常都会应用在哪些场景当中呢? 硬防服务器中一般会配备入侵检测系统和预防系统&#x…...

如何将联系人从 iPhone 转移到 Android
从 iPhone 换到 Android 手机时,你可能需要保留重要的数据,例如通讯录。好在,将通讯录从 iPhone 转移到 Android 手机非常简单,你可以从本文中学习 6 种可靠的方法,确保随时保持连接,不错过任何信息。 第 1…...
Nginx server_name 配置说明
Nginx 是一个高性能的反向代理和负载均衡服务器,其核心配置之一是 server 块中的 server_name 指令。server_name 决定了 Nginx 如何根据客户端请求的 Host 头匹配对应的虚拟主机(Virtual Host)。 1. 简介 Nginx 使用 server_name 指令来确定…...

C# 类和继承(抽象类)
抽象类 抽象类是指设计为被继承的类。抽象类只能被用作其他类的基类。 不能创建抽象类的实例。抽象类使用abstract修饰符声明。 抽象类可以包含抽象成员或普通的非抽象成员。抽象类的成员可以是抽象成员和普通带 实现的成员的任意组合。抽象类自己可以派生自另一个抽象类。例…...
HTML前端开发:JavaScript 常用事件详解
作为前端开发的核心,JavaScript 事件是用户与网页交互的基础。以下是常见事件的详细说明和用法示例: 1. onclick - 点击事件 当元素被单击时触发(左键点击) button.onclick function() {alert("按钮被点击了!&…...

第 86 场周赛:矩阵中的幻方、钥匙和房间、将数组拆分成斐波那契序列、猜猜这个单词
Q1、[中等] 矩阵中的幻方 1、题目描述 3 x 3 的幻方是一个填充有 从 1 到 9 的不同数字的 3 x 3 矩阵,其中每行,每列以及两条对角线上的各数之和都相等。 给定一个由整数组成的row x col 的 grid,其中有多少个 3 3 的 “幻方” 子矩阵&am…...

技术栈RabbitMq的介绍和使用
目录 1. 什么是消息队列?2. 消息队列的优点3. RabbitMQ 消息队列概述4. RabbitMQ 安装5. Exchange 四种类型5.1 direct 精准匹配5.2 fanout 广播5.3 topic 正则匹配 6. RabbitMQ 队列模式6.1 简单队列模式6.2 工作队列模式6.3 发布/订阅模式6.4 路由模式6.5 主题模式…...
NPOI操作EXCEL文件 ——CAD C# 二次开发
缺点:dll.版本容易加载错误。CAD加载插件时,没有加载所有类库。插件运行过程中用到某个类库,会从CAD的安装目录找,找不到就报错了。 【方案2】让CAD在加载过程中把类库加载到内存 【方案3】是发现缺少了哪个库,就用插件程序加载进…...
第7篇:中间件全链路监控与 SQL 性能分析实践
7.1 章节导读 在构建数据库中间件的过程中,可观测性 和 性能分析 是保障系统稳定性与可维护性的核心能力。 特别是在复杂分布式场景中,必须做到: 🔍 追踪每一条 SQL 的生命周期(从入口到数据库执行)&#…...