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

news2024/11/28 6:36:47

思维导图

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);

                //更新maxfd
                if(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);

                    //更新maxfd
                    for(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.coloradmin.cn/o/1399293.html

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

相关文章

【51单片机Keil+Proteus8.9】控制步进电机+LCD1602显示状态

步进电机控制 设计思路 电路设计&#xff1a; 选用AT89C51单片机作为电路核心部件&#xff0c;外加LM016L液晶显示屏作为显示&#xff0c;显示步进电机的Fast&#xff0c;Slow&#xff0c;Stop的三个状态将AT89C51单片机所选引脚与LM016L控制引脚相连&#xff0c;再将数据通…

【计算机网络】3、IPv6、网络三层模型、网络的规划与设计、网络的规划与设计、网络存储技术、网络地址翻译NAT、默认网关、虚拟局域网VLAN、虚拟专用网VPN、URL

文章目录 IPv6IPv6的特点IPv4和IPv6的过渡期间主要采用三种基本技术双协议栈隧道技术翻译技术 网络三层模型核心层汇聚层接入层 网络的规划与设计工作区子系统水平布线子系统管理子系统垂直干线子系统设备间子系统建筑群子系统总结 廉价磁盘网络存储技术直接附加存储(DAS)网络附…

在WIN从零开始在QMUE上添加一块自己的开发板(二)

文章目录 一、前言往期回顾 二、CPU虚拟化&#xff08;一&#xff09;相关源码&#xff08;二&#xff09;举个例子&#xff08;三&#xff09;测试 三、内存虚拟化&#xff08;一&#xff09;相关源码&#xff08;二&#xff09;举个例子测试 参考资料 一、前言 笔者这篇博客…

电力能源三维可视化合集 | 图扑数字孪生

电力能源是现代社会发展和运行的基石&#xff0c;渗透于工业、商业、农业、家庭生活等方方面面&#xff0c;它为经济、生活质量、环境保护和社会发展提供了巨大的机会和潜力。图扑软件应用自研 HT for Web 强大的渲染引擎&#xff0c;助力现代化的电力能源数字孪生场景&#xf…

新手也能看懂的【前端自动化测试入门】!

前言 最近在网上搜索前端自动化测试相关的文档&#xff0c;但是发现网上的文章都是偏使用&#xff0c;没有把一些基础概念说清楚&#xff0c;导致后续一口气遇到一些karma、Jasmine、jest、Mocha、Chai、BDD等词汇的时候很容易一头雾水&#xff0c;这次一方面整理一下收获的知…

Mysql运维篇(一) 日志类型

一路走来&#xff0c;所有遇到的人&#xff0c;帮助过我的、伤害过我的都是朋友&#xff0c;没有一个是敌人&#xff0c;如有侵权请留言&#xff0c;我及时删除。 一、mysql相关日志 首先&#xff0c;我们能接触到的&#xff0c;一般我们排查慢查询时&#xff0c;会去看慢查询…

Dicom标准里的 RescaleType

DCM_RescaleType 0x0028, 0x1054 这个 HU 和 us 是代表什么含义 之前去一个公司面试&#xff0c;问我&#xff0c; MR里灰阶是什么 CT里才叫CT值&#xff0c; MR里叫什么呢&#xff1f; DICOMLookup

LabVIEW振动筛螺栓松动故障诊断

LabVIEW振动筛螺栓松动故障诊断 概述&#xff1a;利用LabVIEW解决振动筛螺栓松动的故障诊断问题。通过集成的方法&#xff0c;不仅提高了故障检测的准确性&#xff0c;还优化了维护流程&#xff0c;为类似的机械设备故障提供了可靠的解决方案。 由于工作条件复杂&#xff0c;…

MySQL(五)——多表查询

上期文章 MySQL&#xff08;四&#xff09;——约束 文章目录 上期文章多表关系一对多&#xff08;多对一&#xff09;多对多多表外键关系可视化一对一 多表查询概述笛卡尔积多表查询分类连接查询 内连接隐式内连接显式内连接 外连接左外连接右外连接 自连接联合查询 union&am…

Redis 安装与入门,全文干货

1、简介 Redis 是一个开源的&#xff0c;基于内存的数据存储系统&#xff0c;它可以用作数据库、缓存和消息中间件。它支持多种类型的数据结构&#xff0c;如字符串&#xff08;strings&#xff09;&#xff0c;散列&#xff08;hashes&#xff09;&#xff0c;列表&#xff08…

非科班转码的秋招复盘:地理信息科学GIS专业到后端研发、软件开发

本文介绍地理信息科学&#xff08;GIS&#xff09;专业的2024届应届生&#xff0c;在研三上学期期间&#xff0c;寻找后端研发、软件开发等IT方向工作的非科班转码秋招情况。 首先&#xff0c;这篇文章一开始写于2023年年底&#xff0c;当时为了参加一个征文活动&#xff0c;所…

多维表格产品vika多维表、Flowus、Wolai体验记录

昨天从下午6点肝到凌晨2点多体验低代码平台多维表格产品&#xff0c;体验了3个国内产品&#xff0c;vika多维表、Flowus、Wolai。 具有多维表格新型关系数据库的鼻祖是 Airtable&#xff0c;国内模仿产品有vika多维表、飞书多维表格等。 还有一种类型就是以在国内鼎鼎大名的N…

【Linux】信号量基于环形队列的生产消费模型

信号量 信号量的本质是一个计数器&#xff0c;可以用来衡量临界资源中资源数量多少 信号量的PV操作 P操作&#xff1a;申请信号量称为P操作&#xff0c;P操作的本质就是让计数器减1。 V操作&#xff1a;释放信号量称为V操作&#xff0c;V操作的本质就是让计数器加1 POSIX信号量…

javaWebssh运动会管理系统myeclipse开发mysql数据库MVC模式java编程计算机网页设计

一、源码特点 java ssh运动会管理系统是一套完善的web设计系统&#xff08;系统采用ssh框架进行设计开发&#xff09;&#xff0c;对理解JSP java编程开发语言有帮助&#xff0c;系统具有完整的源代码和数据库&#xff0c;系统主要采用B/S模式开发。开发环境为TOMCAT7.0,M…

SystemVerilog中数组内置函数sum()的一个注意点

Systemverilog内置了数组求和运算方法(sum())&#xff0c;将数组的所有元素累加起来&#xff0c;返回一个最终值。在使用时要注意数组类型的位宽&#xff0c;通常情况下&#xff0c;如果你将一组单bit的值加起来&#xff0c;Systemverilog会使用足够的精度来确保不丢失任何bit的…

Flink处理函数(2)—— 按键分区处理函数

按键分区处理函数&#xff08;KeyedProcessFunction&#xff09;&#xff1a;先进行分区&#xff0c;然后定义处理操作 1.定时器&#xff08;Timer&#xff09;和定时服务&#xff08;TimerService&#xff09; 定时器&#xff08;timers&#xff09;是处理函数中进行时间相关…

python开发之远程开发工具对比

前言 除了本地开发外&#xff0c;还有一种常见的开发方式就是远程开发&#xff0c;一般情况是一台Windows或mac笔记本作为日常使用的电脑&#xff0c;另有一台linux服务器作为开发服务器。开发服务器的性能往往较强&#xff0c;这样远程开发的方式一方面可以让我们在习惯的系统…

PWM实现呼吸灯

PWM也属于51中的重要章节&#xff0c;本节主要介绍呼吸灯&#xff0c;目的是理解PWM的工作原理&#xff0c;PWM的实验案例重点还得看后续的舵机&#xff08;下一节会讲到&#xff09; 那么何为呼吸灯。呼吸灯的定义是&#xff1a;灯光实现由亮到暗的变化或由暗到亮的逐渐变化。…

一篇文章搞懂什么是测试,测试是干什么的?

&#x1f525; 交流讨论&#xff1a;欢迎加入我们一起学习&#xff01; &#x1f525; 资源分享&#xff1a;耗时200小时精选的「软件测试」资料包 &#x1f525; 教程推荐&#xff1a;火遍全网的《软件测试》教程 &#x1f4e2;欢迎点赞 &#x1f44d; 收藏 ⭐留言 &#x1…

信号处理专题设计-基于边缘检测的数字图像分类识别

目录 一、实验目的 二、实验要求 三、实验原理 1.卷积神经网络&#xff08;CNN&#xff09;模型 2.边缘检测 3.形态学操作 4.鲁棒性 四、实验过程 1.数据预处理 2. 网络的构建 3.模型的训练 4.边缘检测和形态学操作相关代码 5.模型训练结果 6.关键信息的保存 五、实验测试与评估…