嵌入式学习-网络编程-Day5

思维导图

select完成tcp并发服务器模型:

服务器端

#include <myhead.h>
#define SER_PORT 8888
#define SER_IP "192.168.122.153"int main(int argc, const char *argv[])
{//1.创建套接字int sfd  = socket(AF_INET,SOCK_STREAM,0/*IPPROTO_TCP*/);if(sfd==-1){perror("socket error");return -1;}printf("sfd=%d\n",sfd);//将端口号快速重用函数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);//2.2绑定if(bind(sfd,(struct sockaddr*)&sin,sizeof(sin))==-1){perror("bind error");return -1;}printf("bind success %s %s %d\n",__FILE__,__func__,__LINE__);//3.将套接字设置成监听状态if(listen(sfd,128)==-1){perror("listen error");return -1;}printf("listen success %s %s %d\n",__FILE__,__func__,__LINE__);//4.阻塞等待客户端的链接请求//4.1定义容器接收客户端的地址信息struct sockaddr_in cin;   //用于接收地址信息socklen_t socklen = sizeof(cin);  //用于接收地址信息的大小int newfd=-1;//准备一个文件描述符容器fd_set readfds,tempfds;//清空容器FD_ZERO(&readfds);//将要监测的文件描述符放入集合FD_SET(0,&readfds);FD_SET(sfd,&readfds);//定义一个变量存储容器中的最大的文件描述符int maxfd=sfd;//顶替一个地址信息结构体数组,每一个元素对应一个客户端文件描述符struct sockaddr_in cin_arr[1024];while(1){tempfds = readfds;//使用select函数对容器中的文件描述符进行赋值int res = select(maxfd+1,&tempfds,0,0,0);if(res==9){perror("select error");return -1;}else if(res==0){printf("timeout\n");return -1;}//判断是否是文件描述符触发事件for(int cli=0;cli<=maxfd;cli++){if(!FD_ISSET(cli,&tempfds)){continue;}//程序执行至此,说明已经有时间产生并且解除了select的阻塞//并且此时文件描述符集合中只剩下本次触发事件对应的文件描述符//判断哪个文件描述符还在集合中,如果在,就执行相关函数if(cli==0){char wbuf[128]="";scanf("%s",wbuf);printf("触发了终端输入事件---\n");if(strcmp(wbuf,"quit")==0){goto END;}//将消息发送给所有客户端for (int i = 4; i <= maxfd; i++){sendto(i,wbuf,sizeof(wbuf),0,(struct sockaddr*)&cin_arr[i],sizeof(cin_arr[i]));}}else if(cli==sfd){//接受客户端的链接if((newfd =accept(sfd,(struct sockaddr*)&cin,&socklen))==-1){perror("accept error");return -1;}printf("您有一个新的客户端[%s:%d]发来连接请求 success %s %s %d\n",\inet_ntoa(cin.sin_addr),ntohs(cin.sin_port),__FILE__,__func__,__LINE__);//更新地址信息结构体数组cin_arr[newfd]=cin;//将newfd放入readfds中FD_SET(newfd,&readfds);//更新maxfdif(newfd>maxfd){maxfd=newfd;}}else{//跟客户端进行消息通信char buf[128]="";bzero(buf,sizeof(buf));int res=recv(cli,buf,sizeof(buf),0);if(res==0){puts("客户端已经下线");close(cli);FD_CLR(cli,&readfds);//更新maxfdfor(int i=maxfd;i>=sfd;i--){if(FD_ISSET(i,&readfds)){maxfd=i;break;}}continue;}printf("[%s:%d] : %s\n",inet_ntoa(cin_arr[cli].sin_addr),ntohs(cin_arr[cli].sin_port),buf);//给客户端发送消息strcat(buf,"=-=");send(cli,buf,sizeof(buf),0);printf("发送成功\n");}}}END://6.关闭套接字close(sfd);return 0;
}
#include <myhead.h>
#define SER_PORT 8888
#define SER_IP "192.168.122.153"
#define CLI_PORT 6666
#define CLI_IP "192.168.122.153"int main(int argc, const char *argv[])
{//1.创建套接字int cfd  = socket(AF_INET,SOCK_STREAM,0/*IPPROTO_TCP*/);if(cfd==-1){perror("socket error");return -1;}printf("cfd=%d\n",cfd);
/*//将端口号快速重用函数int reuse =1;if(setsockopt(cfd,SOL_SOCKET,SO_REUSEADDR,&reuse,sizeof(reuse))==-1){perror("setsockopt error");return -1;}printf("端口号快速重用成功\n");//2.绑定(随意)struct sockaddr_in cin;cin.sin_family=AF_INET;cin.sin_port=htons(CLI_PORT);cin.sin_addr.s_addr=inet_addr(CLI_IP);if(bind(cfd,(struct sockaddr*)&cin,sizeof(cin))==-1){perror("bind error");return -1;}printf("bind success %s %s %d\n",__FILE__,__func__,__LINE__);*///3.连接服务器//3.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);//3.2链接if(connect(cfd,(struct sockaddr*)&sin,sizeof(sin))==-1){perror("");return -1;}printf("链接成功\n");//准备文件描述符容器fd_set readfds,tempfds;//清空容器FD_ZERO(&readfds);//将要监测的文件描述符放入集合FD_SET(0,&readfds);FD_SET(cfd,&readfds);//4.收发数据char buf[128]="";while(1){tempfds = readfds;//使用select函数对容器中的文件描述符进行赋值int res = select(cfd+1,&tempfds,0,0,0);if(res==-1){perror("select error");return -1;}else if(res==0){printf("timeout\n");return -1;}//判断是否是文件描述符触发事件if(FD_ISSET(0,&tempfds)){bzero(buf,sizeof(buf));printf("请输入>>>\n");fgets(buf,sizeof(buf),stdin);buf[strlen(buf)-1]=0;//发送给服务器send(cfd,buf,sizeof(buf),0);printf("发送成功\n");if(strcmp(buf,"quit")==0){break;}}else if(FD_ISSET(cfd,&tempfds)){//接收服务器发来的消息recv(cfd,buf,sizeof(buf),0);printf("[%s:%d]:%s\n",SER_IP,SER_PORT,buf);}}//5.关闭套接字close(cfd);return 0;
}

实现结果

9ea4193ec0726eea426720a854d4b9c.png

poll完成tcp并发服务器模型:

#include <myhead.h>
#define SER_PORT 8888
#define SER_IP "192.168.122.153"int main(int argc, const char *argv[])
{//1.创建套接字int sfd  = socket(AF_INET,SOCK_STREAM,0/*IPPROTO_TCP*/);if(sfd==-1){perror("socket error");return -1;}printf("sfd=%d\n",sfd);//将端口号快速重用函数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);//2.2绑定if(bind(sfd,(struct sockaddr*)&sin,sizeof(sin))==-1){perror("bind error");return -1;}printf("bind success %s %s %d\n",__FILE__,__func__,__LINE__);//3.将套接字设置成监听状态if(listen(sfd,128)==-1){perror("listen error");return -1;}printf("listen success %s %s %d\n",__FILE__,__func__,__LINE__);//4.阻塞等待客户端的链接请求//4.1定义容器接收客户端的地址信息struct sockaddr_in cin;   //用于接收地址信息socklen_t socklen = sizeof(cin);  //用于接收地址信息的大小int newfd=-1;//定义一个等待文件描述符结构体数组struct pollfd pfd[10];//填充要等待的文件描述符及事件pfd[0].fd=0;pfd[0].events=POLLIN;pfd[1].fd=sfd;pfd[1].events=POLLIN;int client_num=0;//定义一个地址信息结构体数组,每一个元素对应一个客户端文件描述符struct sockaddr_in cin_arr[1024];while(1){//阻塞监测集合中是否有事件产生int res=poll(pfd,client_num+2,-1);if(res==-1){perror("poll error");return -1;}else if(res==0){printf("timeout\n");return -1;}if(pfd[0].revents==POLLIN){char wbuf[128]="";scanf("%s",wbuf);printf("触发了终端输入事件---\n");if(strcmp(wbuf,"quit")==0){break;}//将消息发送给所有客户端for (int i = 4; i <= client_num+3; i++){//sendto(i,wbuf,sizeof(wbuf),0,(struct sockaddr*)&cin_arr[i],sizeof(cin_arr[i]));send(i,wbuf,sizeof(wbuf),0);}}if(pfd[1].revents==POLLIN){//接受客户端的链接if((newfd =accept(sfd,(struct sockaddr*)&cin,&socklen))==-1){perror("accept error");return -1;}printf("您有一个新的客户端[%s:%d]发来连接请求 success %s %s %d\n",\inet_ntoa(cin.sin_addr),ntohs(cin.sin_port),__FILE__,__func__,__LINE__);client_num++;pfd[1+client_num].fd=newfd;pfd[1+client_num].events=POLLIN;printf("客户端连接成功\n");}for(int cli=0;cli<client_num;cli++){if(pfd[cli+2].revents==POLLIN){//跟客户端进行消息通信char buf[128]="";bzero(buf,sizeof(buf));int res=recv(pfd[cli+2].fd,buf,sizeof(buf),0);if(res==0){puts("客户端已经下线");close(pfd[cli+2].fd);client_num--;continue;}//printf("[%s:%d] : %s\n",inet_ntoa(cin_arr[cli].sin_addr),ntohs(cin_arr[cli].sin_port),buf);printf("收到消息:%s\n",buf);//给客户端发送消息strcat(buf,"=-=");send(pfd[cli+2].fd,buf,sizeof(buf),0);printf("发送成功\n");}}}//6.关闭套接字close(sfd);return 0;
}
#include <myhead.h>
#define SER_PORT 8888
#define SER_IP "192.168.122.153"
#define CLI_PORT 6666
#define CLI_IP "192.168.122.153"int main(int argc, const char *argv[])
{//1.创建套接字int cfd  = socket(AF_INET,SOCK_STREAM,0/*IPPROTO_TCP*/);if(cfd==-1){perror("socket error");return -1;}printf("cfd=%d\n",cfd);
/*//2.绑定(随意)struct sockaddr_in cin;cin.sin_family=AF_INET;cin.sin_port=htons(CLI_PORT);cin.sin_addr.s_addr=inet_addr(CLI_IP);if(bind(cfd,(struct sockaddr*)&cin,sizeof(cin))==-1){perror("bind error");return -1;}printf("bind success %s %s %d\n",__FILE__,__func__,__LINE__);
*///3.连接服务器//3.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);//3.2链接if(connect(cfd,(struct sockaddr*)&sin,sizeof(sin))==-1){perror("");return -1;}printf("链接成功\n");//定义一个等待文件描述符结构体数组struct pollfd pfd[2];//填充要等待的文件描述符及事件pfd[0].fd=0;pfd[0].events=POLLIN;pfd[1].fd=cfd;pfd[1].events=POLLIN;//4.收发数据char buf[128]="";while(1){//阻塞监测集合中是否有事件产生int res=poll(pfd,2,-1);if(res==-1){perror("poll error");return -1;}else if(res==0){printf("timeout\n");return -1;}if(pfd[0].revents==POLLIN){bzero(buf,sizeof(buf));printf("请输入:");fgets(buf,sizeof(buf),stdin);buf[strlen(buf)-1]=0;//发送给服务器send(cfd,buf,sizeof(buf),0);printf("发送成功\n");if(strcmp(buf,"quit")==0){break;}}if(pfd[1].revents==POLLIN){//接收服务器发来的消息recv(cfd,buf,sizeof(buf),0);printf("[%s:%d]:%s\n",SER_IP,SER_PORT,buf);}}//5.关闭套接字close(cfd);return 0;
}

实现结果

88b1249f3882e2217ec0b8afa3dd55e.png

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

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

相关文章

Linux系统三剑客之grep和正则表达式的介绍(一)

1.正则表达式 目录 1.正则表达式 1.什么是正则表达式 &#xff1f; 2.正则表达式的使用场景 3.正则表达式字符表示 4.它们之间的区别 2.grep命令 作用&#xff1a; 语法&#xff1a; 说明&#xff1a; 选项&#xff1a;options 重点 实例 3.后面的下次再更新。 …

MongoDB Compass当前版本及历史版本下载安装

mongoDB compass 当前版本下载 官网 https://www.mongodb.com/try/download/compass 官网下载一般只能下载最新版本。 github https://github.com/mongodb-js/compass MongoDB Compass与MongoDB的版本对应关系 MongoDB CompassMongoDB1.9.12MongoDB 2.6.11 Community

QT通过QPdfWriter类实现pdf文件生成与输出

一.QPdfWriter类介绍 本文代码工程下载地址&#xff1a; https://download.csdn.net/download/xieliru/88736664?spm1001.2014.3001.5503 QPdfWrite是一个用于创建PDF文件的类&#xff0c;它是Qt库的一部分。它提供了一些方法和功能&#xff0c;使您能够创建和写入PDF文件。…

PHP反序列化总结4--原生类总结

原生类的简要介绍以及原生类和反序列化的关系 PHP 原生类指的是 PHP 内置的类&#xff0c;它们可以直接在 PHP 代码中使用且无需安装或导入任何库&#xff0c;相当于代码中的内置方法例如echo &#xff0c;print等等可以直接调用&#xff0c;但是原生类就是可以就直接php中直接…

翻译: Streamlit从入门到精通 显示图表Graphs 地图Map 主题Themes 二

Streamlit从入门到精通 系列&#xff1a; 翻译: Streamlit从入门到精通 基础控件 一 1. 使用Streamlit显示图表Graphs 1.1 为什么我们需要可视化&#xff1f; 数据可视化通过将数据整理成更容易理解的格式来讲述故事&#xff0c;凸显趋势和异常点。好的可视化能够讲述一个故…

如何定位和优化程序CPU、内存等性能之巅

目录 摘要 引言 关注 指标 正文 定位CPU瓶颈 定位内存瓶颈 定位IO瓶颈 总结 摘要 性能优化指在不影响系统运行正确性的前提下&#xff0c;使之运行得更快&#xff0c;完成特定功能所需的时间更短&#xff0c;或拥有更强大的服务能力。本文将介绍性能优化的基本概念以…

Logback的配置文件,你看懂了吗

参考文章一 参考文章二 configuration是XML文件根元素。root和logger可视为同一类&#xff0c;都是日志设置&#xff1b;root是日志的全局设置&#xff0c;而logger可以单独设置某一些包和类的日志输出。appender配置日志格式、如何过滤、文件处理等。property和contextName元…

(N-140)基于springboot,vue协同过滤推荐算法个性化购物商城

开发工具&#xff1a;IDEA 服务器&#xff1a;Tomcat9.0&#xff0c; jdk1.8 项目构建&#xff1a;maven 数据库&#xff1a;mysql5.7 系统分前后台&#xff0c;项目采用前后端分离 前端技术&#xff1a;vueelementUI 服务端技术&#xff1a;springbootmybatisredis 本…

yarn包管理器在添加、更新、删除模块时,在项目中是如何体现的

技术很久不用&#xff0c;就变得生疏起来。对npm深受其害&#xff0c;决定对yarn再整理一遍。 yarn包管理器 介绍安装yarn帮助信息最常用命令 介绍 yarn官网&#xff1a;https://yarn.bootcss.com&#xff0c;学任何技术的最新知识&#xff0c;都可以通过其对应的网站了解。无…

下一代 Vue3 Devtools 正式开源

什么是 Vue DevTools Vue DevTools 是一个旨在增强 Vue 开发人员体验的工具,它提供了一些功能来帮助开发者更好地了解 Vue 应用程序。 Vue DevTools:Unleash Vue Developer Experience. Enhance your Vue development journey with an amazing experience! 典型的功能特征包…

【数据结构】二叉树(遍历,递归)

&#x1f308;个人主页&#xff1a;秦jh__https://blog.csdn.net/qinjh_?spm1010.2135.3001.5343&#x1f525; 系列专栏&#xff1a;《数据结构》https://blog.csdn.net/qinjh_/category_12536791.html?spm1001.2014.3001.5482 ​​​ 目录 二叉树遍历规则 前序遍历 ​…

day-13 拿出最少数目的魔法豆

思路 将beans的每个数值当做袋子最后豆子剩余数&#xff0c;选择取豆子最少的一种方案 解题方法 //从小到大&#xff0c;将每个beans[i]作为剩余豆子数 //对于beans[i]&#xff0c;i之前的全为零&#xff0c;i之后的全变为beans[i] ansMath.min(ans,sum-(beans.length-i)*bean…