基于DUP的网络聊天室

基于UDP的网络聊天室的使用(select)完成的服务器端

#include<head.h>
typedef struct de
{
	char name[10];
	struct sockaddr_in cin;
	struct de* next;
}*linklist;
//创建节点
linklist a_creat()
{
	linklist p=(linklist)malloc(sizeof(struct de));
	p->next=NULL;
	bzero(p->name,sizeof(p->name));
	return p;
}
//判断是否是新用户上线
linklist panduan(char *buf,struct sockaddr_in cin,linklist head,int sfd)
{
	linklist p=head;
	while(p->next!=NULL)
	{
		if(p->cin.sin_addr.s_addr==cin.sin_addr.s_addr && p->cin.sin_port==cin.sin_port)
		{
			return head;
		}
		p=p->next;
	}
	linklist q=a_creat();
	q->next=head;
	q->cin=cin;
	strcpy(q->name,buf);
	head=q;
	char sbuf[20]="";
	strcpy(sbuf,q->name);
	strcat(sbuf,"上线");
	printf("%s\n",sbuf);
	while(q->next!=NULL)
	{
		q=q->next;
		sendto(sfd,sbuf,sizeof(sbuf),0,(struct sockaddr*)&(q->cin),sizeof(q->cin));
	}
	return head;
	
}
//释放内存,并且删除该节点
linklist free_t(linklist q,linklist head)
{
	if(q==head)
	{
		head=q->next;
		q->next=NULL;
		free(q);
		return head;
	}
	linklist p=head;
	while(p->next!=q)
	{
		p=p->next;
	}
	p->next=q->next;
	q->next=NULL;
	free(q);
	return head;

}
int main(int argc, const char *argv[])
{
	//1、创建套接字文件
	int sfd=socket(AF_INET,SOCK_DGRAM,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;
	}
	printf("端口号快速重用成功\n");

	//2、绑定
	//2.1填充地址信息结构体
	struct sockaddr_in sin;
	sin.sin_family=AF_INET;
	sin.sin_port=htons(8888);
	sin.sin_addr.s_addr=inet_addr("192.168.122.22");

	//2.2绑定工作
	if(bind(sfd,(struct sockaddr*)&sin,sizeof(sin))==-1)
	{
		perror("bind error");
		return -1;
	}
	//3.定义变量存放客户端地址信息结构体
	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);
	linklist head=a_creat();
	linklist Mhead=head;
	while(1)
	{
		Mhead=head;
		tempfds=readfds;
		int res=select(sfd+1,&tempfds,NULL,NULL,NULL);
		if(res==-1)
		{
			perror("select error");
			return -1;
		}
		else if(res==0)
		{
			printf("timeout\n");
			return -1;
		}
		if(FD_ISSET(0,&tempfds))//服务器发送消息
		{
			char rbuf[128]="";
			bzero(rbuf,sizeof(rbuf));
			scanf("%s",rbuf);
			printf("发送成功\n");
			linklist p=head;
			while(p->next!=NULL)
			{
				sendto(sfd,rbuf,sizeof(rbuf),0,(struct sockaddr*)&(p->cin),sizeof(p->cin));
				p=p->next;
			}
			if(strcmp(rbuf,"quit")==0)
			{
				close(sfd);
				printf("服务器下线\n");
				return 0;
			}
		}
		if(FD_ISSET(sfd,&tempfds))
		{
			char sbuf[128]="";
			recvfrom(sfd,sbuf,sizeof(sbuf),0,(struct sockaddr*)&cin,&socklen);
			head=panduan(sbuf,cin,head,sfd);//判断是否是有用户上线
			if(head==Mhead)//如果头指针没发生改变,说明是链表中的用户发来消息
			{
				linklist yy=head;
				while(yy->next!=NULL)
				{
					if(yy->cin.sin_addr.s_addr==cin.sin_addr.s_addr && yy->cin.sin_port==cin.sin_port)//找到用户对应的名字,并且将消息转发给其他用户
					{
						char dbuf[128]="";
						strcpy(dbuf,yy->name);
						if(strcmp(sbuf,"quit")==0)//判断该用户是否下线
						{
							strcat(dbuf,"下线");
							head=free_t(yy,head);
							linklist ss=head;
							while(ss->next!=NULL)
							{
								if(ss!=yy)
								{
									sendto(sfd,dbuf,sizeof(dbuf),0,(struct sockaddr*)&(ss->cin),sizeof(ss->cin));
								}
								ss=ss->next;
							}
							break;
						}
						strcat(dbuf,":");
						strcat(dbuf,sbuf);
						printf("[%d]%s\n",ntohs(yy->cin.sin_port),dbuf);
						linklist ss=head;
						while(ss->next!=NULL)
						{
							if(ss!=yy)
							{
								sendto(sfd,dbuf,sizeof(dbuf),0,(struct sockaddr*)&(ss->cin),sizeof(ss->cin));
							}
							ss=ss->next;
						}
						break;
					}
					yy=yy->next;
				}
			}
		}
	}


	return 0;
}

使用多进程完成的客户端

#include<head.h>
void handle(int arg)
{
	if(arg==SIGCHLD)
	{
		while(waitpid(-1,NULL,WNOHANG)>0);
	}
}
int main(int argc, const char *argv[])
{
	if(signal(SIGCHLD,handle)==SIG_ERR)
	{
		perror("signal error");
		return -1;
	}
	int sfd=socket(AF_INET,SOCK_DGRAM,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;
	}
	printf("端口号快速重用成功\n");
	//填充服务器地址信息结构体
	struct sockaddr_in sin;
	sin.sin_family=AF_INET;
	sin.sin_port=htons(8888);
	sin.sin_addr.s_addr=inet_addr("192.168.122.22");
	socklen_t socklen=sizeof(sin);
	char buf[128]="";
	printf("请输入登录用户名:");
	scanf("%s",buf);
	sendto(sfd,buf,sizeof(buf),0,(struct sockaddr*)&sin,sizeof(sin));
	pid_t pid=fork();
	while(1)
	{

		if(pid>0)
		{
			//主进程输入并且发送消息
			bzero(buf,sizeof(buf));
			fgets(buf,sizeof(buf),stdin);
			buf[strlen(buf)-1]='\0';
			sendto(sfd,buf,sizeof(buf),0,(struct sockaddr*)&sin,sizeof(sin));
			if(strcmp(buf,"quit")==0)
			{
				close(sfd);
				printf("你已下线\n");
				return 0;
			}
		}else if(pid==0)
		{
			//子进程接收消
			bzero(buf,sizeof(buf));
			recvfrom(sfd,buf,sizeof(buf),0,(struct sockaddr*)&sin,&socklen);
			printf("%s\n",buf);
		}
	}
	return 0;
}

结果

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

Flink SQL

Flink SQL 来源&#xff1a;B站尚硅谷 sql-client准备 Table API和SQL是最上层的API&#xff0c;在Flink中这两种API被集成在一起&#xff0c;SQL执行的对象也是Flink中的表&#xff08;Table&#xff09;&#xff0c;所以我们一般会认为它们是一体的。Flink是批流统一的处理…

LSTM学习笔记

上一篇文章中我们提到&#xff0c;CRNN模型中用于预测特征序列上下文的模块为双向LSTM模块&#xff0c;本篇中就来针对该模块的结构和实现做一些理解。 Bidirectional LSTM模块结构如下图所示&#xff1a; 在Pytorch中&#xff0c;已经集成了LSTM模块&#xff0c;定义如下&…

Spring成长之路—Spring MVC

在分享SpringMVC之前&#xff0c;我们先对MVC有个基本的了解。MVC(Model-View-Controller)指的是一种软件思想&#xff0c;它将软件分为三层&#xff1a;模型层、视图层、控制层 模型层即Model&#xff1a;负责处理具体的业务和封装实体类&#xff0c;我们所知的service层、poj…

【开源】基于JAVA语言的中学生家校互联系统

目录 一、摘要1.1 项目介绍1.2 项目录屏 二、功能模块2.1 学生管理模块2.2 课堂表现模块2.3 考试成绩模块2.4 家校留言模块2.5 校园通知模块 三、系统设计3.1 用例设计3.2 实体类设计3.2.1 课堂表现实体类设计3.2.2 考试成绩实体类设计3.2.3 家校留言实体类设计3.2.4 校园通知实…

AWS 专题学习 P8 (ECS、EKS、Lambda、CloudFront、DynamoDB)

文章目录 什么是 Docker&#xff1f;操作系统上的 DockerDocker 镜像存储Docker vs. Virtual MachinesDocker 入门AWS 中的 Docker Containers Management Amazon ECSEC2 Launch TypeFargate Launch TypeECS 的 IAM RolesLoad Balancer IntegrationsData Volumes (EFS)ECS Serv…

HCIA——20应用层:C/S、P2P、peer

学习目标&#xff1a; 计算机网络 1.掌握计算机网络的基本概念、基本原理和基本方法。 2.掌握计算机网络的体系结构和典型网络协议&#xff0c;了解典型网络设备的组成和特点&#xff0c;理解典型网络设备的工作原理。 3.能够运用计算机网络的基本概念、基本原理和基本方法进行…

产品经理学习-产品运营《用户运营策略》

⽤户画像与⽤户运营策略 什么是用户画像 对产品运营而言&#xff0c;用户画像就是对用户的各种特征贴上标签通过这些标签将用户分成不同的用户群体 为用户提供有针对性的服务。 制作用户画像是为了专注和精准 使产品的服务对象更加聚焦&#xff0c;更加专注&#xff1b;根据产…

红包封面免费送1000个,你设计,我出额度

相信最近大家或多或少都知道了吧&#xff0c;腾讯又又又给大家&#xff0c;准确的说是给一年勤奋的公众号/视频号博主一个福利 根据不同博主的粉丝、更新频度以及作品质量&#xff0c;给力博主们免费制作红包封面的福利 比如我这个号&#xff0c;有6000额度 那这6000个&#…

Python武器库开发-武器库篇之Fofa-API使用(四十六)

Python武器库开发-武器库篇之Fofa-API使用(四十六) FOFA&#xff08;FOcus Observation of Futures Assets&#xff09;是一款专业的网络资产搜索引擎&#xff0c;旨在帮助企业发现和评估网络上的潜在安全风险。FOFA的基本原理是通过搜索引擎的方式&#xff0c;按照关键词对互…

Civil 3D安装教程,免费使用,带安装包和工具,一分钟轻松搞的安装

前言 Civil 3D是一款面向基础设施行业的建筑信息模型&#xff08;BIM&#xff09;解决方案。它为基础设施行业的各类技术人员提供了强大的设计、分析以及文档编制功能&#xff0c;广泛适用于勘察测绘、岩土工程、交通运输、水利水电、市政给排水、城市规划和总图设计等众多领域…

【Spring 篇】MyBatis核心配置文件解密:数据之门的守护精灵

欢迎来到MyBatis的幕后花絮&#xff0c;今天我们将深入解析MyBatis的核心配置文件&#xff0c;这个神秘的数据之门的守护精灵。这份配置文件是连接你的应用程序和数据库之间的纽带&#xff0c;也是整个MyBatis舞台背后的幕后工作者。在这篇博客中&#xff0c;我们将揭开核心配置…

ES框架详解

ES框架详解 1、全文检索的介绍 ​ 那么对于一般的公司&#xff0c;初期是没有那么多数据的&#xff0c;所以很多公司更倾向于使用传统的数据库&#xff1a;mysql&#xff1b;比如我们要查找关键字”传智播客“&#xff0c;那么查询的方式大概就是:select * from table where …

vue3项目eslint配置、配置prettier(格式化配置)

文章链接: 全部配置链接 第一步:eslint配置、配置prettier(代码格式化):点击链接 (1) .eslint.cjs—eslint配置文件 (2).eslintignore—校验忽略文件 (3).prettierrc.json添加规则 (4).prettierignore忽略文件 prettierrc规范说明: npm install -D eslint-plugin-import…

修复uni-simple-router@2.0.7版本query参数null的bug

问题&#xff1a;query参数为null或者为空时&#xff0c;插件内部参数校验问题导致的会报错&#xff1a;TypeError: Cannot convert undefined or null to object at Function.keys 源码修改如下&#xff1a; 通过打补丁的方式修复query参数类型校验问题 1. 安装patch-packag…

SPI 动态服务发现机制

SPI&#xff08;Service Provier Interface&#xff09;是一种服务发现机制&#xff0c;通过ClassPath下的META—INF/services文件查找文件&#xff0c;自动加载文件中定义的类&#xff0c;再调用forName加载&#xff1b; spi可以很灵活的让接口和实现分离&#xff0c; 让API提…

Packet Tracer - 配置第 3 层交换和VLAN间路由

地址分配表 设备 接口 IP 地址/前缀 MLS VLAN 10 192.168.10.254 /24 MLS VLAN 10 2001:db8:acad:10::1/64 MLS VLAN 20 192.168.20.254 /24 MLS VLAN 20 2001:db8:acad:20::1/64 MLS VLAN 30 192.168.30.254/24 MLS VLAN 30 2001:db8:acad:30::1/64 MLS …

免费三款备受推崇的爬虫软件

在信息爆炸的时代&#xff0c;爬虫软件成为了数据采集、信息挖掘的得力工具。为了解决用户对优秀爬虫软件的需求&#xff0c;本文将专心分享三款备受推崇的爬虫软件&#xff0c;其中特别突出推荐147采集软件&#xff0c;为您开启爬虫软件的奇妙世界。 一、爬虫软件的重要性 爬…

Hive数仓框架详解

Hive框架详解 1、Hive的介绍 ​ Hive是基于Hadoop的一个数据仓库工具&#xff0c;可以将结构化的数据文件映射为一张数据库表&#xff0c;并提供类SQL查询功能。 ​ 本质是将SQL转换为MapReduce程序。 ​ 主要用途&#xff1a;用来做离线数据分析&#xff0c;比直接用MapRed…

Python圣诞主题绘图:用turtle库打造冬日奇妙画面【第31篇—python:圣诞节】

文章目录 Python圣诞主题绘图导言代码结构概览详细解析drawlight函数tree函数xzs函数drawsnow函数五角星的绘制 完整代码代码解析总结 Python圣诞主题绘图 导言 圣诞季节是个充满欢乐和创意的时刻。在这个技术博客中&#xff0c;我们将深入探讨如何使用Python的turtle库创建一…

MySQL LIKE 子句

昨天介绍了 MySQL 数据库使用 DELETE 语句来删除数据&#xff0c;今天主要讲解下 MySQL LIKE 子句。 通过前几天的讲解&#xff0c;我们知道&#xff0c;在 MySQL 中使用 SELECT 命令来读取数据&#xff0c; 同时我们可以在 SELECT 语句中使用 WHERE 子句来获取指定的记录。 W…