华清远见嵌入式学习——网络编程——作业4

news2024/10/2 3:29:03

作业要求:①使用IO多路复用中的select函数实现TCP并发服务器客户端

                  ②使用IO多路复用中的poll函数实现TCP并发服务器的服务器端

一、

代码

#include <myhead.h>

#define SERPORT 8888              //服务器端口号
#define SERIP "192.168.114.113"       //服务器IP地址

int main(int argc, const char *argv[])
{
	//创建用于通信的套接字
	int cfd = socket(AF_INET,SOCK_STREAM,0);
	if(cfd == -1)
	{
		perror("socket error");
		return -1;
	}

	//连接服务器
	///填充服务器地址信息结构体
	struct sockaddr_in sin;
	sin.sin_family = AF_INET;
	sin.sin_port = htons(SERPORT);
	sin.sin_addr.s_addr = inet_addr(SERIP);

	///连接服务器
	if(connect(cfd,(struct sockaddr *)&sin,sizeof(sin)) == -1)
	{
		perror("connect error");
		return -1;
	}
	
	//创建用于检测文件描述符的集合
	fd_set readfds,tempfds;
	
	//清空集合
	FD_ZERO(&readfds);
	
	//将要检测的文件描述符放入集合中
	FD_SET(cfd,&readfds);
	FD_SET(0,&readfds);

	int res = 0;    //接收select的返回值
	int maxfd = cfd;  //集合中值最大的文件描述符

	//向服务器进行数据的收发
	char buf[128] = "";
	int ret = 0;    //接收recv的返回值
	while(1)
	{
		tempfds = readfds;
	
		res = select(maxfd+1,&tempfds,NULL,NULL,NULL);
		if(res == -1)
		{
			perror("select error");
			return -1;
		}else if(res == 0)
		{
			printf("time out\n");
			return -1;			
		}
		
		//遍历集合中所有的文件描述符
		for(int i = 0;i <= maxfd;i++)
		{
			//判断当前文件描述符是否在集合中
			if(!FD_ISSET(i,&readfds))
			{
				continue;
			}
	
			
			//判断0号文件描述符是否还在集合中
			if(0 == i)
			{
				//从标准输入中读取数据
				fgets(buf,sizeof(buf),stdin);
				buf[strlen(buf)-1] == 0;

				//将数据发送到服务器
				if(send(cfd,buf,sizeof(buf),0) == -1)
				{
					perror("send error");
					return -1;
				}

			}else if(cfd == i)     //判断cfd是否还在集合中
			{
				//接收来自服务器的消息
				ret = recv(cfd,buf,sizeof(buf),0);
				if(ret == -1)
				{
					perror("recv error");
					return -1;
				}else if(ret == 0)
				{
					printf("服务器已关闭\n");
					return -1;
				}
				
				printf("服务器消息:%s\n",buf);
			}
		}
	}
	
	//关闭文件描述符
	close(cfd);
	
	return 0; 
}

效果图

二、

代码

#include <myhead.h>

#define IP "192.168.114.118"
#define PORT 8888

int main(int argc, const char *argv[])
{
	//创建用于连接的套接字
	int sfd = socket(AF_INET,SOCK_STREAM,0);
	if(sfd == -1)
	{
		perror("socket error");
		return -1;
	}

	//设置端口号快速重用
	int reuse = 1;
	if(setsockopt(sfd, SOL_SOCKET, SO_REUSEADDR, &reuse, sizeof(reuse)) == -1)
	{
		perror("setsockopt error");
		return -1;
	}

	//绑定服务器IP和端口号
	///填充服务器地址信息结构体
	struct sockaddr_in sin;
	sin.sin_family = AF_INET;
	sin.sin_port = htons(PORT);
	sin.sin_addr.s_addr = inet_addr(IP);

	///绑定
	if(bind(sfd,(struct sockaddr *)&sin,sizeof(sin)) == -1)
	{
		perror("bind error");
		return -1;
	}
	printf("bind success\n");

	//将连接用套接字设置为被动监听状态
	if(listen(sfd,128) == -1)
	{
		perror("listen error");
		return -1;
	}
	printf("listen success\n");

	//定义一个集合管理sfd和打开的通信用文件描述符
	struct pollfd fds[1024];
	int maxfd = 0;


	//手动放入sfd
	fds[0].fd = sfd;
	fds[0].events = POLLIN;     //表明为读事件

	//将fds中其余元素初始化为-1
	for(int i = 4;i <= 1024;i++)
	{
		fds[i].fd = -1;
	}

	//填充客户端地址信息结构体
	struct sockaddr_in cin;
	cin.sin_family = AF_INET;
	socklen_t socklen = sizeof(cin);


	char cbuf[128] = "";  //给客户端用的容器
	int nfd;
	int res = 0;  //接收poll返回的结果
	while(1)
	{
		res = poll(fds,maxfd+1,-1);
		if(res == -1)
		{
			perror("select");
			return -1;
		}
		else if(res == 0)
		{
			continue;;
		}
		else if(res > 0)                //说明检测到了有文件描述符对应的缓冲区的数据发生了改变
		{
			if(fds[0].revents ==  POLLIN)    //表明有新的客户连接进来了
			{
				int nfd = accept(sfd,(struct sockaddr*)&cin,&socklen);  //阻塞在此处,直到有客户端连接上来
				if(nfd == -1)   //增加这些错误的判断非常重要,可以帮助找到出现问题的地方
				{
					perror("accept");
					return -1;
				}

				//将新的文件描述符加入到集合中
				for(int i = 1;i < 1024;i++)
				{
					if( fds[i].fd == -1)
					{
						fds[i].fd = nfd;
						fds[i].events = POLLIN;
						break;
					}
				}

				//更新最大的文件描述符
				if(nfd > maxfd)
				{
					maxfd = nfd;
				}
			}

			for(int i = 1;i <= maxfd;i++)     //轮询客户端对应的文件描述符
			{
				if(fds[i].revents == POLLIN)  //说明此文件描述符对应的客户端发送来了数据
				{
					int ret = read(fds[i].fd,cbuf,sizeof(cbuf));
					if(ret == -1)
					{
						perror("read");
						exit(-1);
					}
					else if(ret == 0)
					{
						printf("client closed\n");
						close(fds[i].fd);   //关闭对应的文件描述符
						fds[i].fd = -1;   //在fds中清空对应的文件描述符
					}
					else if(ret > 0)
					{
						printf("read buf = %s\n",cbuf);
						write(fds[i].fd,cbuf,strlen(cbuf)+1);
					}


				}
			}
		}
	}
	//关闭所有套接字
	close(sfd);

	return 0;

}

效果图

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

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

相关文章

python二叉树链树_树的链式存储结构

二叉链树是一种树状数据结构&#xff0c;其中每个节点最多有两个子节点&#xff0c;分别称为左子节点和右子节点。每个节点包含一个数据元素和指向其左右子节点的指针。二叉链树可以是空树&#xff0c;也可以是具有以下特点的非空树&#xff1a; 1. 每个节点最多有两个子节点。…

【AGC】集成AGC服务上架应用市场审核问题

【关键字】 AGC、应用市场、审核 【问题描述】 集成了AGC服务&#xff0c;上架到应用市场不通过&#xff0c;检查发现是com.huawei.secure.android.common.ssl.util.c.doInBackground 存在获取安装列表行为。 已经按照sdk 设置了&#xff0c;但是检测还是有授权前去获取安装列…

UniApp打包教程:使用HBuilder X和AppUploader完成原生App云打包和上架指南“

目录 uniapp进行打包 使用上架工具appuplode进行发包 1.登录appuploder软件 2.登陆开发者App Store后台 uniapp进行打包 在HBuilder X编辑器中打开需要打包的项目&#xff0c;然后点击上面菜单栏中 发行 > 原生App-云打包&#xff0c;对以下弹出的弹窗进行内容填写 填写完…

Modbus转Profinet网关连接PLC与天信流量计通讯案例

本文将为您详细介绍如何成功连接PLC与天信流量计&#xff1a;从选择合适的Modbus转Profinet网关开始&#xff0c;到设置网关以实现通讯连接&#xff0c;还会涵盖部署和故障排除过程中可能遇到的一些问题。 首先&#xff0c;选择合适的Modbus转Profinet网关至关重要。我们选用基…

《微信小程序开发从入门到实战》学习二十七

3.4 开发参与投票页面 3.4.2 借用伪造数据开发功能 为了便于开发&#xff0c;新建一个编译模式&#xff1a; 之前没看文章&#xff0c;每次都习惯性填完投票创建的信息提交再跳转看效果。好累。 添加变异模式开发真方便。 另外&#xff0c;点击提交后没跳转到投票页面&#…

Oracle中文显示???????解决办法

项目场景&#xff1a; Oracleoracle中文显示???解决办法 问题描述 原因分析&#xff1a; Oracle中文显示???通常是由于字符集不匹配或者编码问题导致的。当数据库中的数据使用的是某种字符集&#xff0c;而客户端或者应用程序使用的是另一种字符集时&#xff0c;就会出…

基于51单片机的病床呼叫系统设计

**单片机设计介绍&#xff0c; 基于51单片机的病床呼叫系统设计 文章目录 一 概要二、功能设计设计思路 三、 软件设计原理图 五、 程序六、 文章目录 一 概要 基于51单片机的病床呼叫系统是一种用于医疗机构的设备&#xff0c;旨在提供快速、可靠的病人呼叫和监控功能。以下是…

使用yum安装jdk,并配置环境变量

写在前面: yum安装的jdk&#xff0c;默认不用配置环境变量就可以java -version显示结果&#xff0c;但是却不能在系统环境变量中查看到JAVA_HOME&#xff0c;由于其他应用需要这个环境变量&#xff0c;比如hadoop&#xff0c;所以这里说明如何进行java的相关环境变量配置 1. y…

基于springboot实现实习管理系统的设计与实现项目【项目源码+论文说明】计算机毕业设计

基于sprinmgboot实现实习管理系统的设计与实现演示 摘要 随着信息化时代的到来&#xff0c;管理系统都趋向于智能化、系统化&#xff0c;实习管理也不例外&#xff0c;但目前国内仍都使用人工管理&#xff0c;市场规模越来越大&#xff0c;同时信息量也越来越庞大&#xff0c;…

11月23日星期四今日早报简报微语报早读

11月23日星期四&#xff0c;农历十月十一&#xff0c;早报微语早读。 1、我国5G基站总数达321.5万个&#xff1b; 2、2023年两院院士增选结果揭晓&#xff0c;共133人当选&#xff1b; 3、北京低保标准提升至每人每月1395元&#xff1b; 4、上海制定体育发展条例&#xff1a…

2023 年亚马逊黑色星期五和网络星期一的企业电子商务指南

亚马逊黑色星期五和网络星期一 周末即将到来&#xff01;感恩节于 11 月 23 日举行&#xff0c;紧接着是 24 日黑色星期五和 27 日网络星期一。您的亚马逊业务准备好应对大量涌入了吗&#xff1f; 我们相信您已经准备好黑色星期五优惠并准备好库存&#xff0c;以确保您有足够的…

小型洗衣机哪个牌子好用又耐用?最好用的迷你洗衣机

随着大家工作的压力越来越大&#xff0c;下了班之后只能想躺平&#xff0c;在洗完澡之后看着还需要手洗的内衣裤真的很头疼。有些小伙伴还有会攒几天再丢进去洗衣机里面一起&#xff0c;而且这样子是非常不好的&#xff0c;用过的内衣裤长时间不清洗容易滋生细菌&#xff0c;而…

在线接口测试工具fastmock使用

1、fastmock线上数据模拟器 在平时的项目测试中&#xff0c;尤其是前后端分离的时候&#xff0c;前端人员需要测试调用后端的接口&#xff0c;这个时候会出现测试不方便的情况。此时我们可以使用fastmock平台在线上模拟出一个可以调用的接口&#xff0c;方便前端人员进行数据测…

合伙人注册即得/创业平台扶持!

问心一语持续体验中~ 与公司签订线下&#xff08;线上&#xff09;纸质合伙人代理合同&#xff0c;具备法律效力。 一级直推、非一级直推注册即得奖励。(消耗完毕被邀请用户赠送的AI免费使用条数) 即&#xff1a;邀请1人注册即得并消耗&#xff01;只需注册无需充值&#xff…

YOLOV5标注训练自己的数据全流程教程

概述 yolo在目标检测领域是非常有代表性的模型&#xff0c;它速度快识别效果也很精准&#xff0c;是实时检测模型中应用最广泛的。yolo的原理和代码是很容易获得的&#xff0c;且有各式各样的教程&#xff0c;但是模型怎么使用的教程相对比较少。本文讲解如何使用yolov5模型训…

Tekton — 通过tekton-operator部署tekton组件

文章目录 版本信息部署准备安装卸载tekton组件 Tektoncd Operator 作为一个 Kubernetes 的扩展&#xff0c;可以方便快捷地在 Kubernetes 集群上安装、升级和管理 Tekton Pipelines、Dashboard、Triggers 等组件。 那么本篇文章介绍在K8S集群中如何通过tekton-operator部署Tekt…

基于单片机的空气质量实时监测系统(论文+源码)

1. 系统设计 通过文献和市场调查&#xff0c;本设计的实现方案框架是以单片机为核心控制处理器搭建外围的功能模块如温度传感器模块、湿度传感器检测模块、二氧化碳传感器检测设备模块、无线通信模块和蜂鸣器声光报警提示模块来实现&#xff0c;辅以显示模块来展示。 该系统通…

分布式篇---第一篇

系列文章目录 文章目录 系列文章目录前言一、分布式幂等性如何设计?二、简单一次完整的 HTTP 请求所经历的步骤?三、说说你对分布式事务的了解前言 前些天发现了一个巨牛的人工智能学习网站,通俗易懂,风趣幽默,忍不住分享一下给大家。点击跳转到网站,这篇文章男女通用,…

测绘资质地理信息系统工程乙级申请要求材料

新测绘资质分为10个专业 1.大地测量 2.测绘航空摄影 3.摄影测量与遥感 4.工程测量 5.海洋测绘 6.界线与不动产测绘 7.地理信息系统工程 8.地图编制 9.导航电子地图制作 10.互联网地图服务。 新《测绘资质管理办法》和《测绘资质分类分级标准》&#xff0c;自2021年7…