网络编程day040830

news2025/1/6 18:38:57

目录

select的TCP服务器

代码

完成select的TCP客户端

代码

结果

思维导图


select的TCP服务器
代码
#include<myhead.h>

//do-while只是为了不让花括号单独存在,并不循环
#define ERR_MSG(msg) do{\
	fprintf(stderr,"%d:",__LINE__);\
	perror(msg);\
}while(0);

#define PORT 8888//端口号1024-49151
#define IP "192.168.114.118"//本机IP,终端输入ifconfig可得

int main(int argc, const char *argv[])
{
	//创建流式套接字 socket
	int sfd = socket(AF_INET,SOCK_STREAM,0);
	if(sfd<0){
		//printf("%d:",__LINE__);
		//perror("socket error");
		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 ip
	struct sockaddr_in sin;
	sin.sin_family 		= AF_INET;//必须填AF_INET
	sin.sin_port   		= htons(PORT);//端口号的网络字节序
	sin.sin_addr.s_addr = inet_addr(IP);//本机IP
	//绑定服务器的地址信息  -->必须绑定    bind
	if(bind(sfd,(struct sockaddr*)&sin,sizeof(sin))<0){
		ERR_MSG("bind");
		return -1;
	}//指针类型的强转不会有数据丢失
	printf("bind success\n");

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

	//定义文件描述符集合
	fd_set readfds,tmpfds;

	//将文件描述符集合清空
	FD_ZERO(&readfds);
	//将文件描述符放入集合之中
	FD_SET(sfd,&readfds);
	FD_SET(0, &readfds);

	int maxfd = sfd;
	int res;
	char buf[128] = "";
	struct sockaddr_in cin;  //存储客户端的地址信息
	socklen_t addrlen = sizeof(cin);  //真实的地址信息结构体的大小
	//获取一个已经完成的客户端信息,生成一个新的文件描述符 accept
	int newfd;
	struct sockaddr_in saveCin[1024];  //备份连接成功的客户端的地址信息,用下标来对应地址信息
	while(1){
		tmpfds = readfds;

		//调用select函数
		res = select(maxfd+1,&tmpfds, NULL, NULL, NULL);
		if(res < 0){
			ERR_MSG("select error");
			break;
		}else if(0 == res){
			printf("time out\n");
			break;
		}else{
			for(int i=0; i<=maxfd; i++){
				if(0==FD_ISSET(i, &tmpfds)){
					continue;
				}else if(-1==FD_ISSET(i, &tmpfds)){
					ERR_MSG("FD_ISSET error");
					break;
				}

				if(0==i){
					//终端输入
					printf("从终端读取成功::");
					fgets(buf,sizeof(buf),stdin);

					buf[strlen(buf)-1] = 0;

					printf("%s\n",buf);
				}
				else if(sfd == i){
					if((newfd=accept(sfd,(struct sockaddr*)&cin,&addrlen))<0){
						ERR_MSG("accept");
						return -1;


					}
					printf("[%s:%d]客户端链接成功 newfd = %d\n",\
							inet_ntoa(cin.sin_addr),\
							ntohs(cin.sin_port),newfd);

					saveCin[newfd] = cin;  //将cin另存到下标为文件描述符的位置

					//将newfd添加到集合中
					FD_SET(newfd, &readfds);

					//更新maxfd
					maxfd = maxfd>newfd?maxfd:newfd;


				}else{
					if(FD_ISSET(i, &readfds)){
						//清空字符串
						bzero(buf,sizeof(buf)); //memset

						//接收
						res = recv(i, buf, sizeof(buf) ,0);
						if(res<0){
							ERR_MSG("recv");
							return -1;
						}else if(0==res){
							printf("[%s:%d]客户端下线 newfd=%d\n",\
									inet_ntoa(saveCin[i].sin_addr),\
									ntohs(saveCin[i].sin_port),i);
							//将文件描述符从集合中踢出
							FD_CLR(i, &readfds);
							//由于踢出的文件描述符可能是最大文件描述符,更新maxfd
							/*		for(; maxfd>=0; maxfd--){
									if(FD_ISSET(maxfd, &readfds)){
									break;
									}
									}	*/

							while(FD_ISSET(maxfd, &readfds)==0 && maxfd-->=0);

							//关闭文件描述符
							close(i);
							continue;
						}
						printf("[%s:%d]客户端消息 newfd=%d:%s\n",\
								inet_ntoa(saveCin[i].sin_addr),\
								ntohs(saveCin[i].sin_port),i,buf);	


						//发送
						strcat(buf,">_<");
						if(send(i,buf,strlen(buf),0)<0){
							ERR_MSG("send");
							return -1;
						}
						printf("send success\n");			
					}				


				}
			}
/*
			//如果是终端输入就绪
			if(FD_ISSET(0,&tmpfds)){
				printf("从终端读取成功::");
				fgets(buf,sizeof(buf),stdin);

				buf[strlen(buf)-1] = 0;

				printf("%s\n",buf);
			}

			//如果是客户端连接就绪
			if(FD_ISSET(sfd,&tmpfds)){
				if((newfd=accept(sfd,(struct sockaddr*)&cin,&addrlen))<0){
					ERR_MSG("accept");
					return -1;


				}
				printf("[%s:%d]客户端链接成功 newfd = %d\n",\
						inet_ntoa(cin.sin_addr),\
						ntohs(cin.sin_port),newfd);

				saveCin[newfd] = cin;  //将cin另存到下标为文件描述符的位置

				//将newfd添加到集合中
				FD_SET(newfd, &readfds);

				//更新maxfd
				maxfd = maxfd>newfd?maxfd:newfd;
			}
			for(int i=4; i<=maxfd; i++){
				if(FD_ISSET(i, &readfds)){
					//清空字符串
					bzero(buf,sizeof(buf)); //memset

					//接收
					res = recv(i, buf, sizeof(buf) ,0);
					if(res<0){
						ERR_MSG("recv");
						return -1;
					}else if(0==res){
						printf("[%s:%d]客户端下线 newfd=%d\n",\
								inet_ntoa(saveCin[i].sin_addr),\
								ntohs(saveCin[i].sin_port),i);
						//将文件描述符从集合中踢出
						FD_CLR(i, &readfds);
						//由于踢出的文件描述符可能是最大文件描述符,更新maxfd
						for(; maxfd>=0; maxfd--){
							if(FD_ISSET(maxfd, &readfds)){
								break;
							}
						}	

						while(FD_ISSET(maxfd, &readfds)==0 && maxfd-->=0);

						//关闭文件描述符
						close(i);
						continue;
					}
					printf("[%s:%d]客户端消息 newfd=%d:%s\n",\
							inet_ntoa(saveCin[i].sin_addr),\
							ntohs(saveCin[i].sin_port),i,buf);	


					//发送
					strcat(buf,">_<");
					if(send(i,buf,strlen(buf),0)<0){
						ERR_MSG("send");
						return -1;
					}
					printf("send success\n");			
				}
			}*/
		}
	}


	//关闭文件描述符
	close(newfd);
	if(close(sfd)<0){
		ERR_MSG("close");
		return -1;
	}


	return 0;
}
完成select的TCP客户端
代码
#include<myhead.h>

//do-while只是为了不让花括号单独存在,并不循环
#define ERR_MSG(msg) do{\
	fprintf(stderr,"%d:",__LINE__);\
	perror(msg);\
}while(0);

#define PORT 8888//端口号1024-49151
#define IP "192.168.114.118"//本机IP,终端输入ifconfig可得

int main(int argc, const char *argv[])
{
	//创建流式套接字 socket
	int cfd = socket(AF_INET,SOCK_STREAM,0);
	if(cfd<0){
		//printf("%d:",__LINE__);
		//perror("socket error");
		ERR_MSG("socket");
		return -1;
	}
	printf("socket create success sfd=%d\n",cfd);

	//填充服务器的地址信息结构体给connect函数连接
	//相连接哪个服务器就输入哪个服务器的地址信息
	//真是的地址信息结构体根据地址族制定 AF_INET:man 7 ip
	struct sockaddr_in sin;
	sin.sin_family 		= AF_INET;//必须填AF_INET
	sin.sin_port   		= htons(PORT);//服务器绑定的端口号的网络字节序
	sin.sin_addr.s_addr = inet_addr(IP);//服务器绑定的IP
	socklen_t addrlen    = sizeof(sin);
	//连接指定服务器 connect
	if(connect(cfd,(struct sockaddr*)&sin,addrlen)<0){
		ERR_MSG("connect");
		return -1;
	}

	char buf[128] = "";
	ssize_t res = 0;

	//定义文件描述符集合
	fd_set readfds,tmpfds;
	//初始化集合
	FD_ZERO(&readfds);
	//把cfd加入集合
	FD_SET(cfd, &readfds);
	//把标准输入加入集合
	FD_SET(0, &readfds);
	int ret = -1;
	while(1){
		tmpfds = readfds;
		ret = select(cfd+1, &tmpfds, NULL, NULL, NULL);

		if(ret<0){
			ERR_MSG("select error");
			break;
		}else if(0 == ret){
			printf("time out\n");
			break;
		}else{
			if(FD_ISSET(0, &tmpfds)){
				//说明有来自终端的输入,需要发送
				//清空字符串
				bzero(buf,sizeof(buf)); //memset
				printf("请输入>> ");
				fgets(buf,sizeof(buf),stdin);
				buf[strlen(buf)-1] = 0;

				//发送
				strcat(buf,">_<");
				if(send(cfd,buf,strlen(buf),0)<0){
					ERR_MSG("send");
					return -1;
				}
				printf("send success\n");
			}

			if(FD_ISSET(cfd, &tmpfds)){
				//套接字文件的接收缓冲区有数据,需要接收
				//说明有来自终端的输入,需要发送
				//清空字符串
				bzero(buf,sizeof(buf)); //memset

				//接收
				res = recv(cfd, buf, sizeof(buf) ,0);
				if(res<0){
					ERR_MSG("recv");
					return -1;
				}else if(0==res){
					printf("[%s:%d]服务器下线 cfd=%d\n",\
							inet_ntoa(sin.sin_addr),\
							ntohs(sin.sin_port),cfd);
					break;
				}
				printf("[%s:%d]服务器消息 cfd=%d:%s\n",\
						inet_ntoa(sin.sin_addr),\
						ntohs(sin.sin_port),cfd,buf);
			}

		}

	
	}


/*
	while(1){
		//清空字符串
		bzero(buf,sizeof(buf)); //memset
		printf("请输入>> ");
		fgets(buf,sizeof(buf),stdin);
		buf[strlen(buf)-1] = 0;

		//发送
		strcat(buf,">_<");
		if(send(cfd,buf,strlen(buf),0)<0){
			ERR_MSG("send");
			return -1;
		}
		printf("send success\n");

		//接收
		res = recv(cfd, buf, sizeof(buf) ,0);
		if(res<0){
			ERR_MSG("recv");
			return -1;
		}else if(0==res){
			printf("[%s:%d]服务器下线 cfd=%d\n",\
					inet_ntoa(sin.sin_addr),\
					ntohs(sin.sin_port),cfd);
			break;
		}
		printf("[%s:%d]服务器消息 cfd=%d:%s\n",\
					inet_ntoa(sin.sin_addr),\
					ntohs(sin.sin_port),cfd,buf);		
	}
*/
	//关闭文件描述符
	//close(newfd);
	if(close(cfd)<0){
		ERR_MSG("close");
		return -1;
	}


	return 0;
}
结果

思维导图

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

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

相关文章

Python代码雨

系列文章 序号文章目录直达链接1浪漫520表白代码https://want595.blog.csdn.net/article/details/1306668812满屏表白代码https://want595.blog.csdn.net/article/details/1297945183跳动的爱心https://want595.blog.csdn.net/article/details/1295031234漂浮爱心https://want…

JAVA设计模式第七讲:设计模式在 Spring 源码中的应用

设计模式&#xff08;design pattern&#xff09;是对软件设计中普遍存在的各种问题&#xff0c;所提出的解决方案。本文以面试题作为切入点&#xff0c;介绍了设计模式的常见问题。我们需要掌握各种设计模式的原理、实现、设计意图和应用场景&#xff0c;搞清楚能解决什么问题…

2022年12月 C/C++(八级)真题解析#中国电子学会#全国青少年软件编程等级考试

C/C++编程(1~8级)全部真题・点这里 第1题:生理周期 人生来就有三个生理周期,分别为体力、感情和智力周期,它们的周期长度为23天、28天和33天。每一个周期中有一天是高峰。在高峰这天,人会在相应的方面表现出色。例如,智力周期的高峰,人会思维敏捷,精力容易高度集中。因…

若依前端vue设置子路径

若依前端vue设置子路径 说明&#xff1a;本文档中以前后端分离版为例&#xff0c;版本为:3.8.6 一设置变量 在.env.development和.env.production 中定义一个变量如VUE_APP_PROJECT_IDENTIFIER # 项目标识字符 VUE_APP_PROJECT_IDENTIFIER admin二引用路径变量 ${process…

在PHP8中统计数组元素个数-PHP8知识详解

在php8中&#xff0c;统计数组元素的个数&#xff0c;有下面几个函数&#xff1a;使用count()函数统计数组元素个数、使用sizeof()函数统计数组元素个数。还讲到了&#xff0c;使用array_count_values()函数来统计数组中每个元素出现的次数。 1、使用count()函数统计数组元素个…

医疗知识图谱 neo4j

开源项目&#xff1a; https://github.com/liuhuanyong/QASystemOnMedicalKG 一.效果 二.需要安装&#xff1a; pip install pyahocorasick pip install py2neo 三.需要修改&#xff1a; 需要改的点&#xff1a; 1.改连接的方式 2.改读文件的方式 MedicalGraph 运行&am…

读懂AUTOSAR,之CAN Driver L-PDU发送和“重入问题”

1. L-PDU发送 L-PDU传输时,Can模块将L-PDU内容ID和数据长度转换为硬件特定格式(如果需要),并触发传输。 [SWS_Can_00059] CAN到内存的数据映射定义为首先发送的CAN数据字节为数组元素0,最后发送的CAN数据字节为数组元素7或63(在CAN FD的情况下)。(SRS_SPAL_12063)[S…

Android图形-Hardware Composer HAL

目录 一、引言 二、概览 三、实现HWC 3.1 为什么是HWC&#xff1f; 3.2 HWC的支持需求 3.3 HWC的实现思路 3.4 HWC的基元 3.5 HIDL接口 3.6 函数指针 3.7 图层和屏幕句柄 3.8 屏幕合成操作 3.9 多个屏幕 3.10 虚拟屏幕合成 3.10.1 模式 3.10.2 输出格式 3.11 同…

房地产微传单制作秘笈

随着科技的快速发展&#xff0c;传统的宣传方式已经无法满足现代人的需求。而电子传单作为一种新型的宣传方式&#xff0c;已经逐渐受到人们的关注和喜爱。特别是对于房地产行业来说&#xff0c;电子传单更是成为了一种节省成本、快速传播的利器。 为了满足各行业的宣传需求&am…

Python接口自动化封装导出excel方法和读写excel数据

一、首先需要思考&#xff0c;我们在页面导出excel&#xff0c;用python导出如何写入文件的 封装前需要确认python导出excel接口返回的是一个什么样的数据类型 如下&#xff1a;我们先看下不对返回结果做处理&#xff0c;直接接收数据类型是一个对象&#xff0c;无法获取返回值…

学单片机有前途吗?

学单片机有前途吗? 个人认为学习任何一门技术都比不学的强&#xff0c;针对学单片机有前途吗?那么比较对象当然就是在整个IT行业做对比。因此我们可以从职业前景、钱景、这几方面综合考量。 学单片机有前途吗?我觉得重要的一点就是是否适合职业生涯发展&#xff0c;总说程序…

STM32F4的USB Slave驱动移植详细步骤及问题解决

文章目录 1、USB库下载2、移植&#xff08;slave&#xff09;2.1、工程准备2.2、USB库准备 2.3、移植1、新建USB相关文件夹2、拷贝3、添加USB相关代码4、添加头文件路径5、修改相关内容1、修改usb_conf.h2、定义全局宏USE_USB_OTG_FS3、修改usbd_storage_msd.c4、修改usbd_usr.…

【蒸汽冷凝器型号和PI控制】具有PID控制的蒸汽冷凝器的动力学模型(MatlabSimulink)

&#x1f4a5;&#x1f4a5;&#x1f49e;&#x1f49e;欢迎来到本博客❤️❤️&#x1f4a5;&#x1f4a5; &#x1f3c6;博主优势&#xff1a;&#x1f31e;&#x1f31e;&#x1f31e;博客内容尽量做到思维缜密&#xff0c;逻辑清晰&#xff0c;为了方便读者。 ⛳️座右铭&a…

离线数仓同步数据3

业务数据_增量表数据同步 1&#xff09;Flume配置概述2&#xff09;Flume配置实操3&#xff09;通道测试4&#xff09;编写Flume启停脚本 1&#xff09;Flume配置概述 Flume需要将Kafka中topic_db主题的数据传输到HDFS&#xff0c;故其需选用KafkaSource以及HDFSSink&#xff…

mysql索引条件下推 、 count(*)、count(1)、IN 、exists等

索引下推 Index Condition Pushdown(ICP)&#xff0c;是一种在存储引擎层使用索引过滤数据的优化方式 如果没有ICP&#xff0c;存储引擎会遍历以定位基表中的行&#xff0c;并将他们返回给mysql服务器&#xff0c;有mysql 服务器评估where 后面的条件是否保留行。启用ICP&…

Debian11安装PostgreSQL+PostGIS+pgRouting ,链接Navicat

船新版本&#xff0c;遵循官网教程 1 准备一个Debian11系统2 从官网安装Postgres2.1 安装Postgres2.2 修改Postgres密码2.3 配置Postgres远程访问 3 安装Postgis、pgRouting4 链接Navicat 1 准备一个Debian11系统 2 从官网安装Postgres 2.1 安装Postgres 1 进入Postgre的官网…

GE IC693CPU374CPU模块

处理能力&#xff1a;IC693CPU374 CPU 模块通常具有高性能的处理器&#xff0c;用于执行复杂的控制逻辑和数据处理任务。 内存容量&#xff1a;它通常具有内置的RAM和Flash存储器&#xff0c;用于存储控制程序、数据和配置信息。 多通信接口&#xff1a;该模块通常具有多个通…

集合的笔记

集合 包装类 泛型类有一个不幸的限制, 不能使用基本类型作为类型参数, 解决办法是使用这个包装类, 每一种基本类型都有对应的包装类 基本类型和它们对应的包装类型之间的转换是自动进行的。在调用 add 方法时&#xff0c;个值为 42 的 Integer 类对象在一种被称为自动装箱的过…

redis(0)-安装实操

1.基本概念 key-value型数据库&#xff0c;秒10万级查询。 2.计算向数据移动 3.安装步骤 3.1总体流程 //源码目录&#xff1a;/home/ftp/redis5 src //安装目录&#xff1a;make install /opt/tang/redis5/bin 只是一些bin文件 //make install 只是把bin 复制到某个路…