嵌入式学习-网络编程-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.mzph.cn/news/632306.shtml

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

相关文章

前端公共组件库优化

背景 前段时间入职了新公司后&#xff0c;做一些内部前端基建的工作&#xff0c;其中一个工作就是优化现有的frontend-common公共组件库。之前的组件库一直是以源码依赖的形式存在&#xff0c;即各个项目通过git submodule的方式将该仓库引入到各个项目中&#xff0c;作为一个…

机器学习--jupyter使用

机器学习–jupyter notebook的使用 Jupyter项目是一个非盈利的开源项目&#xff0c;源于2014年的ipython项目&#xff0c;因为它逐渐发展为支持跨所有编程语言的交互式数据科学和科学计算 Jupyter Notebook&#xff0c;原名IPython Notbook&#xff0c;是IPython的加强网页版…

学习vue3(一)

参考&#xff1a;Vue3TS 快速上手 1.Vue3简介 2020年9月18日&#xff0c;Vue.js发布3.0版本&#xff0c;代号&#xff1a;One Piece&#xff08;海贼王&#xff09;耗时2年多、2600次提交、30个RFC、600次PR、99位贡献者github上的tags地址&#xff1a;https://github.com/vuej…

安卓app签名生成工具

基本信息 | 微信开放文档微信开发者平台文档https://developers.weixin.qq.com/doc/oplatform/Downloads/Android_Resource.html 使用方法:下载模拟器,随后将打包的apk,拉到模拟器中,然后点击上面,的文档,拉到最底下,下载那个软件到模拟器,,随后将打包的包名,输入就可以生成签名…

西门子博途用SCL语言写的入栈出栈

1.用户登录 #pragma code ("useadmin.dll") #include "PWRT_api.h" #pragma code() PWRTLogin(1) 2.用户退出 #pragma code ("useadmin.dll") #include "PWRT_api.h" #pragma code() PWRTLogout(); 3.画面跳转 SetPictureName("P…

解决百度地图在模拟器上运行报 java.lang.IllegalArgumentException: No config chosen问题

解决百度地图在模拟器上运行报 java.lang.IllegalArgumentException: No config chosen 问题 1. 问题复现 在近期公司使用模拟器(网易MuMu)进行项目演示时&#xff0c;在进入存在百度地图(Android版本 7.4.2版本)之后&#xff0c;页面出现奔溃&#xff0c;后台日志为&#xf…

中国多家半导体设备厂表现出色,营收可观 | 百能云芯

多家中国半导体设备大厂近日相继发布了2023年度业绩预告&#xff0c;表现出色&#xff0c;营收和净利润均呈现较大幅度的增长&#xff0c;这一利好消息背后得益于半导体行业周期的复苏以及国产半导体需求的持续增长。 据百能云芯电子元器件商城了解&#xff0c;北方华创发布的公…

智能的精髓在于有效地使用数学与非数学的方法

数学是智能的重要基础&#xff0c;它提供了一种精确、逻辑和可靠的工具&#xff0c;可以用来模拟和解释现实世界的问题。数学可以帮助智能系统建立数学模型&#xff0c;进行数据分析和预测&#xff0c;优化算法和决策等。例如&#xff0c;机器学习和深度学习算法中常用的数学方…

大文件的断点续传如何实现

断点续传 断点续传是一种数据恢复技术&#xff0c;主要用于在读取或发送数据时&#xff0c;因为网络问题、磁盘问题等原因导致数据传输中断。断点续传技术允许你在已经传输的数据基础上继续传输&#xff0c;从而节省数据传输时间。 断点续传通常用于文件传输过程中&#xff0c;…

Github项目推荐--MusicFreeDesktop

项目地址 https://github.com/maotoumao/MusicFreeDesktop 项目简述 这是一个开源的音乐播放器&#xff0c;主要使用typescript编写&#xff0c;页面很漂亮。支持自定义主题和插件化配置音源&#xff0c;是一大亮点。 项目截图

C++大学教程(第九版)5.19求Π的值

题目 代码 #include <bits/stdc.h> using namespace std;int main() {double pai 0;for (int count 1, i 1; count < 1000; i 2, count){int flag 1;if (count % 2 0){flag -1;}pai flag * (4.0 / (i * 1.0));cout << "当取前" << co…

架构篇07-复杂度来源:低成本、安全、规模

文章目录 低成本安全规模小结关于复杂度来源,前面的专栏已经讲了高性能、高可用和可扩展性,今天我们来聊聊复杂度另外三个来源低成本、安全和规模。 低成本 当我们的架构方案只涉及几台或者十几台服务器时,一般情况下成本并不是我们重点关注的目标,但如果架构方案涉及几百…

RabbitMQ入门精讲

1. 什么是消息队列 消息指的是两个应用间传递的数据。数据的类型有很多种形式&#xff0c;可能只包含文本字符串&#xff0c;也可能包含嵌入对象。 “消息队列(Message Queue)”是在消息的传输过程中保存消息的容器。在消息队列中&#xff0c;通常有生产者和消费者两个角色。…

Steam游戏十大骗术及防骗指南

一、buff\igxe网站api问题 骗术总结&#xff1a;骗子利用api链接&#xff0c;在网站发起报价的同时&#xff0c;csgo账号发起同样的报价&#xff1b; 解决方法&#xff1a;在交易网站卖完东西后&#xff0c;在steam注销api链接&#xff0c;下次使用再更换新的。交易过程中核对…

OpenHarmony 应用开发入门 (一、环境搭建及第一个Hello World)

万事开头难。难在迈出第一步。心无旁骛&#xff0c;万事可破。没有人一开始就能想清楚&#xff0c;只有做起来&#xff0c;目标才会越来越清晰。--马克.扎克伯格 前言 2024年1月16日&#xff0c;华为目前开启已HarmonyOS NEXT开发者预览版Beta招募&#xff0c;报名周期为1月15…

鸿蒙开发-ArkUI框架实战【日历应用 】

对于刚刚接触OpenHarmony应用开发的开发者&#xff0c;最快的入门方式就是开发一个简单的应用&#xff0c;下面记录了一个日历应用的开发过程&#xff0c;通过日历应用的开发&#xff0c;来熟悉基本图形的绘制&#xff0c;ArkUI的组件的使用&#xff0c;UI组件生命周期&#xf…

【时间复杂度】时间复杂度优化法则简讲

一、引言 时间复杂度是衡量算法运行效率的一项重要指标&#xff0c;它描述了随着输入规模的增加&#xff0c;算法的执行时间如何增长。在算法设计与分析中&#xff0c;我们经常面临着优化时间复杂度的任务&#xff0c;以便提高程序的性能。本博客将深入探讨时间复杂度的优化法…

redis数据安全(五)事务

一、概念&#xff1a; 1、介绍&#xff1a;Redis 事务的本质是一组命令的集合。事务支持一次执行多个命令&#xff0c;一个事务中所有命令都会被序列化。在事务执行过程&#xff0c;会按照顺序串行化执行队列中的命令&#xff0c;其他客户端提交的命令请求不会插入到事务执行命…

软件测试面试题整理

软件测试的几个阶段 在进行Beta测试之前和之后&#xff0c;通常会进行以下几种测试&#xff1a; 内部测试&#xff08;Internal Testing&#xff09; 在Beta测试之前&#xff0c;开发团队会进行内部测试&#xff0c;对软件进行全面的测试。这个阶段包括单元测试、集成测试和系…

Kafka 消费者如何实现消费者组内分区平衡,Kafka常见面试问题

1、简介 一个消费者组中有多个consumer组成&#xff0c;一个topic有多个partition组成&#xff0c;现在的问题是&#xff0c;到底由哪个consumer来消费哪个partition的数据。或者当某个消费者被移出消费者组&#xff0c;如何实现再平衡。本文将详细介绍。 2、消费者主要分区策…