网络编程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;
}

今日思维导图

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

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

相关文章

网络隔离下实现的文件传输,现有的方式真的安全吗?

在当今的信息化时代&#xff0c;网络安全已经成为了各个企业和机构不可忽视的问题。为了保护内部数据和系统不受外部网络的攻击和泄露&#xff0c;一些涉及国家安全、商业机密、个人隐私等敏感信息的企业和机构&#xff0c;通常会对内外网进行隔离&#xff0c;即建立一个独立的…

Xilinx FPGA 7系列 GTX/GTH Transceivers (4) Aurora 8b10b 递增数收发验证

第一节:Xilinx FPGA 7系列 GTX/GTH Transceivers (1)–了解了GTX硬件的基础知识 第二节:IBERT GTX --通过Ibert IP测试链路通信 第三节:aurora 8b10b single lane 4byte–学习官方历程 递增数验证 自行编写data_gen和data_check 验证aurora 8b10b SFP 1.25G 收发正确。 组…

CentOS在应用程序菜单中创建快捷方式

背景&#xff1a; 在CentOS系统中&#xff0c;安装一些应用软件的时候&#xff0c;我们可能会自定义安装路径&#xff1b;这样在安装完应用程序后&#xff0c;在“Application”下&#xff0c;可能找不到对应的快捷键&#xff1b;这是就需要手动去创建跨界方式。 应用&#xf…

CNN(九):Inception v3算法实战

&#x1f368; 本文为&#x1f517;365天深度学习训练营 中的学习记录博客 &#x1f356; 原作者&#xff1a;K同学啊|接辅导、项目定制 1 理论基础 Inception v3论文 Inception v3由谷歌研究员Christian Szegedy等人在2015年的论文《Rethinking the Inception Architecture f…

ubuntu samba文件共享服务器搭建

目的&#xff1a; 为了实现Android源码在ubuntu的编译&#xff0c;在windows上进行源码的修改和验证&#xff0c;需要在ubuntu系统上搭建共享文件夹&#xff0c;这里将ubuntu的/home/用户/路径下的所有内容共享&#xff0c;方法如下 ubuntu端&#xff1a; 一、samba安装 sud…

【暴力DP】CF1409 F

Problem - F - Codeforces 题意&#xff1a; 思路&#xff1a; 首先有个很明显的结论是&#xff1a;替换的字符一定是那两个字符之一 那么替换成哪个字符贡献更大不确定&#xff0c;因此考虑DP 因为有操作次数限制&#xff0c;直接把操作放进状态里 为了计算贡献&#xff…

机器学习第十一课--K-Means聚类

一.聚类的概念 K-Means算法是最经典的聚类算法&#xff0c;几乎所有的聚类分析场景&#xff0c;你都可以使用K-Means&#xff0c;而且在营销场景上&#xff0c;它就是"King"&#xff0c;所以不管从事数据分析师甚至是AI工程师&#xff0c;不知道K-Means是”不可原谅…

spring:实现初始化动态bean|获取对象型数组配置文件

0. 引言 近期因为要完成实现中间件的工具包组件&#xff0c;其中涉及要读取对象型的数组配置文件&#xff0c;并且还要将其加载为bean&#xff0c;因为使用了spring 4.3.25.RELEASE版本&#xff0c;很多springboot的相关特性无法支持&#xff0c;因此特此记录&#xff0c;以方…

Mac配置iTerm样式终端

一、MacOs系统 MacOs中终端使用iTerm2 1. 配置oh-my-zsh oh my zsh 的地址&#xff1a; https//github.com/ohmyzsh/ohmyzsh 插件存放位置&#xff1a;~/.oh-my-zsh/plugins 下载常用的插件 git clone http://github.com/zsh-users/zsh-syntax-highlighting.git 修改配…

怎么将几张图片做成pdf合在一起

怎么将几张图片做成pdf合在一起&#xff1f;在我们平时的工作中&#xff0c;图片和pdf都是非常重要的电脑文件&#xff0c;使用也非常频繁&#xff0c;图片能够更为直观的展示内容&#xff0c;而pdf则更加的正规&#xff0c;很多重要文件大多会做成pdf格式的。在职场人的日常工…

TypeError: res.data.map is not a function微信小程序报错

从数据库查&#xff1a; 调用的是&#xff1a; 访问的springboot后端是这个&#xff1a; 打印出来如下&#xff1a; 看到是json格式的数据 [Users [id3, name刘雨昕, phone18094637788, admintrue, actionsJsonadmin, createAtSat Sep 16 10:11:20 CST 2023, tokentest], User…

深入了解队列数据结构:定义、特性和实际应用

文章目录 &#x1f34b;引言&#x1f34b;队列的定义&#x1f34b;队列的实现&#x1f34b;队列的应用&#x1f34b;练习题&#x1f34b;结语 &#x1f34b;引言 队列&#xff08;Queue&#xff09;是计算机科学中一种重要的数据结构&#xff0c;它常用于各种应用程序中&#x…

拼多多API接口解析,实现根据ID取商品详情

拼多多是一个流行的电商平台&#xff0c;它提供了API接口供开发者使用。要根据ID获取商品详情&#xff0c;您需要使用拼多多API接口并进行相应的请求。 以下是使用拼多多API接口根据ID获取商品详情的示例代码&#xff08;使用Python编写&#xff09;&#xff1a; import requ…

​专业图像处理软件 Photoshop 2023 mac版本更新(ps2023中文)

​Photoshop 2023 mac是一款图像编辑和图形设计软件&#xff0c;广泛应用于专业人士和爱好者。它提供了许多工具和功能&#xff0c;用于创建、编辑和增强数字图像&#xff0c;包括图层、蒙版、滤镜和各种选择工具。Photoshop还支持多种文件格式&#xff0c;包括psD、JPEG、PNG和…

全套办公软件Office 2019 mac专业版功能

Microsoft office 2019 Beta for Mac 是一款办公软件套装&#xff0c;它包含常用的办公应用程序&#xff0c;如 Word、Excel、PowerPoint 和 Outlook 等。office 2019 Beta 版本是一个测试版本&#xff0c;旨在让用户提前体验下一个版本的 office 套件&#xff0c;以便用户可以…

全国职业技能大赛云计算--高职组赛题卷③(私有云)

全国职业技能大赛云计算--高职组赛题卷③&#xff08;私有云&#xff09; 第一场次题目&#xff1a;OpenStack平台部署与运维任务1 基础运维任务&#xff08;5分&#xff09;任务2 OpenStack搭建任务&#xff08;15分&#xff09;任务3 OpenStack云平台运维&#xff08;15分&am…

2023!6招玩转 Appium 自动化测试

Appium是个什么鬼 Appium是一个移动端的自动化框架&#xff0c;可用于测试原生应用&#xff0c;移动网页应用和混合型应用&#xff0c;且是跨平台的。可用于IOS和Android以及firefox的操作系统。原生的应用是指用android或ios的sdk编写的应用&#xff0c;移动网页应用是指网页…

Leetcode198. 打家劫舍

https://leetcode.cn/problems/house-robber/description/ 你是一个专业的小偷&#xff0c;计划偷窃沿街的房屋。每间房内都藏有一定的现金&#xff0c;影响你偷窃的唯一制约因素就是相邻的房屋装有相互连通的防盗系统&#xff0c;如果两间相邻的房屋在同一晚上被小偷闯入&…

网络初识

一 IP 地址 概念: IP 地址主要用于表示网络主机、其他网络设备&#xff08;如路由器&#xff09;的网络地址。简单说&#xff0c;IP地址用于定位主机的网络地址 格式 IP 地址是一个32为的二进制数&#xff0c;通常被分割为4个“8位二进制数“&#xff08;也就是4个字节&…

layui框架学习(45: 工具集模块)

layui的工具集模块util支持固定条、倒计时等组件&#xff0c;同时提供辅助函数处理时间数据、字符转义、批量事件处理等操作。   util模块中的fixbar函数支持设置固定条&#xff08;2.7版本的帮助文档中叫固定块&#xff09;&#xff0c;是指固定在页面一侧的工具条元素&…