UDP实现群聊通信

news2024/11/23 0:07:27

服务器端

#include <myhead.h>
#define UDPIP "192.168.115.92"
#define UDPPORT 6666
//存储客户信息的链表结构体
typedef struct Node
{
	char name[20];
	struct sockaddr_in cin;
	struct Node *next;
}*linklist;
//数据结构体
struct data_cli
{
	char type;
	char name[20];
	char text[128];
};
//创建节点
linklist create_space()
{
	linklist s=(linklist)malloc(sizeof(struct Node));
	if(NULL==s)
		return NULL;
	bzero(s->name,sizeof(s->name));
	s->next=NULL;
	return s;
}
//末尾插入信息
linklist Insert_end(linklist head,struct sockaddr_in cin,char name[20])
{
	//创建节点
	linklist s=create_space();
	s->cin=cin;
	strcpy(s->name,name);
	//判断之前是否有节点
	if(NULL==head)
	{
		head=s;
		return head;
	}
	linklist p=head;
	while((p->next)!=NULL)
	{
		p=p->next;
	}
	p->next=s;
	//未尾插入
	return head;

}
//删除退出客户
linklist Delete_by_ele(linklist head,in_port_t cin_port)
{
        if(NULL==head)
                return NULL;
        linklist p=head;
	if(NULL==head->next)
	{
		free(head);
		return NULL;
	}
        while(p!=NULL)
        {
	

                if(ntohs(cin_port)==ntohs(p->cin.sin_port))
                {
                        linklist del=p->next;//多个字节
                        p->cin=del->cin;
			strcpy(p->name,del->name);
                        p->next=del->next;
                        free(del);del=NULL;
			return head;
                }
		if(p->next->next==NULL)
		{
			linklist q=p->next;
			free(q);
			p->next=NULL;
			return head;
		}
                p=p->next;
        }
	return head;

}


int main(int argc, const char *argv[])
{
	//创建头指针
	linklist head=NULL;
	//1.创建套接字文件
	int tfd;
	if((tfd=socket(AF_INET,SOCK_DGRAM,0))==-1)
	{
		perror("socket");
		return -1;
	}
	//2.绑定IP和端口
	struct sockaddr_in sin;
	sin.sin_family=AF_INET;
	sin.sin_port=htons(UDPPORT);
	sin.sin_addr.s_addr=inet_addr(UDPIP);
	if(bind(tfd,(struct sockaddr*)&sin,sizeof(sin))==-1)
	{
		perror("bind");
		return -1;
	}
	printf("bind success\n");
	//io多路复用信息
	fd_set readfds,tempfds;
	FD_ZERO(&readfds);
	FD_SET(0,&readfds);
	FD_SET(tfd,&readfds);
	int maxfd=tfd;
	//3.收发信息
	struct sockaddr_in cin1;
	cin1.sin_family=AF_INET;
	socklen_t len=sizeof(cin1);
	char buf[128]="";
	int res;
	struct data_cli cli_data;
	while(1)
	{
		tempfds=readfds;
		//等待唤醒条件
		res=select(maxfd+1,&tempfds,NULL,NULL,NULL);
		if(res<0)
		{
			perror("select");
			return -1;
		}
		else if(res==0)
		{
			printf("超时\n");
			return -1;
		}
		if(FD_ISSET(0,&tempfds))
		{
			
			//系统向所有客户端发消息
			bzero(&cli_data,sizeof(struct data_cli));
			strcpy(cli_data.name,"系统消息:");
			fgets(cli_data.text,sizeof(cli_data.text),stdin);
       			cli_data.text[strlen(cli_data.text)-1]=0;
			linklist p=head;
			while(p!=NULL)
			{
				sendto(tfd,&cli_data,sizeof(struct data_cli),0,(struct sockaddr*)&p->cin,len);
				p=p->next;
			}
			printf("系统发送消息成功\n");

		}
		if(FD_ISSET(tfd,&tempfds))
		{
			bzero(&cli_data,sizeof(struct data_cli));
			recvfrom(tfd,&cli_data,sizeof(struct data_cli),0,(struct sockaddr*)&cin1,&len);
			switch(cli_data.type)
			{
				case 'D':
					{
	  		                        strcpy(cli_data.text,"上线了");
                                                linklist p=head;
                                                while(p!=NULL)
                                                {
                                                sendto(tfd,&cli_data,sizeof(struct data_cli),0,(struct sockaddr*)&p->cin,len);
                                                p=p->next;
                                                }

						head=Insert_end(head,cin1,cli_data.name);
			printf("[%s:%d]:%s\n",inet_ntoa(cin1.sin_addr),ntohs(cin1.sin_port),"登录成功");

					}
					break;
				case 'S':
					{

						linklist p=head;
						while(p!=NULL)
						{
									if(p->cin.sin_port==cin1.sin_port)
									{
										if(p->next!=NULL)
										{
										p=p->next;
										}else{break;}
									}
							sendto(tfd,&cli_data,sizeof(struct data_cli),0,(struct sockaddr*)&p->cin,len);
							p=p->next;
						}
			printf("[%s:%d]:%s\n",inet_ntoa(cin1.sin_addr),ntohs(cin1.sin_port),"客户端发送消息");
		
					}
					break;
				case 'Q':
					{

						head=Delete_by_ele(head,cin1.sin_port);
	  		                        strcpy(cli_data.text,"下线了");
                                                linklist p=head;
                                                while(p!=NULL)
                                                {
                                                sendto(tfd,&cli_data,sizeof(struct data_cli),0,(struct sockaddr*)&p->cin,len);
                                                p=p->next;
                                                }
			printf("[%s:%d]:%s\n",inet_ntoa(cin1.sin_addr),ntohs(cin1.sin_port),"客户端退出");
				
					}
					break;
			}


		}

	}
	//4.关闭文件
	close(tfd);
	return 0;
}

客户端
 

#include <myhead.h>
#define IP "192.168.115.92"
#define PORT 6666
//定义信息结构体
struct data_cli
{
	char type;
	char name[20];
	char text[128];
};
int main(int argc, const char *argv[])
{
	
	//1.创建套接字
	int cfd;
	cfd=socket(AF_INET,SOCK_DGRAM,0);
	if(cfd==-1)
	{
		perror("socket");
		return -1;
	}
	//io多路复用信息
        fd_set readfds,tempfds;
        FD_ZERO(&readfds);
        FD_SET(0,&readfds);
        FD_SET(cfd,&readfds);
        int maxfd=cfd;

	//3.收发数据
	struct sockaddr_in sin;
	sin.sin_family=AF_INET;
	sin.sin_port=htons(PORT);
	sin.sin_addr.s_addr=inet_addr(IP);
	socklen_t len=sizeof(struct sockaddr_in);
	//创建账户
	struct data_cli cli_data;
	bzero(&cli_data,sizeof(struct data_cli));
	printf("请登录用户:");
	cli_data.type='D';
	fgets(cli_data.name,sizeof(cli_data.name),stdin);
	cli_data.name[strlen(cli_data.name)-1]=0;
	char myname[20]="";
	strcpy(myname,cli_data.name);
	sendto(cfd,&cli_data,sizeof(struct data_cli),0,(struct sockaddr*)&sin,len);
	char buf[256]="";
	int res;
	while(1)
	{
                tempfds=readfds;
                //等待唤醒条件
                res=select(maxfd+1,&tempfds,NULL,NULL,NULL);
                if(res<0)
                {
                        perror("select");
                        return -1;
                }
                else if(res==0)
                {
                        printf("超时\n");
                        return -1;
                }
		if(FD_ISSET(0,&tempfds))
		{
			bzero(&cli_data,sizeof(struct data_cli));
			cli_data.type='S';
			strcpy(cli_data.name,myname);
			fgets(cli_data.text,sizeof(cli_data.text),stdin);
			cli_data.text[strlen(cli_data.text)-1]='\0';
			if(strcmp("quit",cli_data.text)==0)
			{
				cli_data.type='Q';
				sendto(cfd,&cli_data,sizeof(struct data_cli),0,(struct sockaddr*)&sin,len);
				break;
			}
			sendto(cfd,&cli_data,sizeof(struct data_cli),0,(struct sockaddr*)&sin,len);
		}
		if(FD_ISSET(cfd,&tempfds))
		{
			bzero(buf,sizeof(buf));
			bzero(&cli_data,sizeof(struct data_cli));
			recvfrom(cfd,&cli_data,sizeof(struct data_cli),0,(struct sockaddr*)&sin,&len);
			sprintf(buf,"[%s]:%s",cli_data.name,cli_data.text);
			printf("%s\n",buf);
		}
	}
	//4.关闭
	close(cfd);
	return 0;
}

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

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

相关文章

Hive安装与配置

你需要掌握&#xff1a; 1.Hive的基本安装&#xff1b; 2.Mysql的安装与设置&#xff1b; 3.Hive 的配置。 注意&#xff1a;Hive的安装与配置建立在Hadoop已安装配置好的情况下。 hadopp安装与配置 Hive 的基本安装 从 官网 下载Hive二进制包&#xff0c;下载好放在/op…

游戏录屏怎么录?学会这几招,轻松搞定!

电子游戏已成为人们日常生活中重要的娱乐方式之一&#xff0c;许多玩家希望在游戏的过程中录制一些精彩的瞬间&#xff0c;或与他人分享自己的游戏体验&#xff0c;因此游戏录屏成为了一种普遍的需求。可是游戏录屏怎么录呢&#xff1f;在本文中&#xff0c;我们将为大家介绍两…

Linux的Sysfs 接口

一、sysfs接口 在linux系统中&#xff0c;用户空间访问驱动程序一般是以“设备文件”的方式通过“read/write/ioctl”访问&#xff0c;还有一种方式&#xff0c;可以通过echo的方式来直接控制硬件或者修改驱动&#xff0c;也能为底层驱动提供一个接口便于应用层调用&#xff0c…

文生图领域经典-ControlNet介绍

引言 2023年的计算机视觉领域顶级学术会议ICCV上&#xff0c;一篇颠覆文生图AI领域的论文《Adding Conditional Control to Text-to-Image Diffusion Models》——ControlNet 荣膺最佳论文奖(Marr奖)。 自开源以来&#xff0c;ControlNet已经在GitHub上揽获25k星。无论是对扩…

物理层之码分复用(内含相关例题)

学习的最大理由是想摆脱平庸&#xff0c;早一天就多一份人生的精彩&#xff1b;迟一天就多一天平庸的困扰。各位小伙伴&#xff0c;如果您&#xff1a; 想系统/深入学习某技术知识点… 一个人摸索学习很难坚持&#xff0c;想组团高效学习… 想写博客但无从下手&#xff0c;急需…

yml转properties工具

目前搜索到的大部分代码都存在以下问题&#xff1a; 复杂结构解析丢失解析后顺序错乱 所以自己写了一个&#xff0c;经过不充分测试&#xff0c;基本满足使用。可以直接在线使用 在线地址 除了yml和properties互转之外&#xff0c;还可以生成代码、sql转json等&#xff0c;可…

数据库系统概述之国产数据库

当今世界&#xff0c;数据已成为重要的生产要素&#xff0c;数据库管理系统更是广泛应用于信息化行业各领域&#xff0c;国内数据库产业能否健康可持续的发展&#xff0c;在很大程度上影响着国民经济发展和网络空间安全。 当前&#xff0c;国产数据库行业竞争非常激烈&#xf…

亚马逊云科技Aurora MySQL在复制性能提升上的不断优化和尝试

前言 Amazon Aurora是亚马逊云科技自研的云原生关系数据库&#xff0c;它在提供和开源数据库MySQL、PostgreSQL的完好兼容性同时&#xff0c;也能够提供和商业数据库媲美的性能和可用性。 Aurora的性能提升不仅包含应用读写吞吐量的提升&#xff0c;也包含复制延迟的降低。一个…

数据结构 / day02作业

1. 有若干个学校人员的信息,包括学生和教师。 其中学生的数据包括&#xff1a;姓名、性别、职业s/S、分数。 教师的数据包括:姓名、性别、职业t/T、职务。 1&#xff0c;定义指针指向堆区内存 2.循环输入 3.计算老师的个数 4.计算学生的平均值 5.循环输出 6释放堆区空间 #inc…

41.0/查询/sql注入安全问题以及解决方式。

41.1. 回顾 1. jdbc&#xff1a;[java database connection] java连接数据库 2. 完成了增删改操作。 [1]加载驱动。Class.forName("com.mysql.cj.jdbc.Driver"); [2]获取连接对象: Connection connDriverManager.getConnection(url,user,pass); url: jdb…

【Cisco Packet Tracer】DHCP/FTP/WEB/DNS实验

本文使用CiscoPacketTracer仿真软件实现了DHCP/FTP/WEB/DNS实验&#xff0c;拓扑中包含2个客户机和3个服务器&#xff08;DHCP服务器、DNS服务器、FTP/WEB公用一个服务器&#xff09;&#xff0c;客户机的IP地址由DHCP服务器动态分配。 DHCP服务器IP地址&#xff1a;192.168.0…

制作电脑微信双开快捷方式

一、介绍 电脑下载的微信正常只能打开一个&#xff0c;那有时候需要双开甚至多开微信我们需要怎么操作呢&#xff1f; 我这里就讲一个制作微信双开快捷键方式的办法&#xff0c;争对其他应用也是一样的原理。 二、制作过程 1、右击微信快捷方式 2、点击属性 3、复制目标 …

nodejs+vue+elementui图书馆教室自习室座位预约管理系统93c8r

本系统利用nodejsVue技术进行开发自习室预约管理系统是未来的趋势。该系统使用的编程语言是nodejs&#xff0c;数据库采用的是MySQL数据库&#xff0c;基本完成了系统设定的目标&#xff0c;建立起了一个较为完整的系统。建立的自习室预约管理系统用户使用浏览器就可以对其进行…

AI旅游:旅游行业的人工智能成熟艺术适应从实践到表现报告

今天分享的是AI系列深度研究报告&#xff1a;《AI旅游&#xff1a;旅游行业的人工智能成熟艺术适应从实践到表现报告》。 &#xff08;报告出品方&#xff1a;accenture&#xff09; 报告共计&#xff1a;25页 旅行还没有充分利用AI所能做的一 而旅游业比两年前强多了。公司…

电脑格式化了怎么恢复原来的数据?您可以这样做

电脑是我们日常生活和工作中不可或缺的工具&#xff0c;然而&#xff0c;在一些情况下我们可能需要进行电脑格式化&#xff0c;比如为了清理系统垃圾、解决系统故障等。然而&#xff0c;格式化会导致所有数据被删除&#xff0c;给用户带来不便和困扰。本文将介绍电脑格式化了怎…

一文搞定XMLHttpRequest,AJAX,Promise,Axios及操作实战

XMLHttpRequest,AJAX,Promise,Axios都是发送异步请求的工具&#xff0c;只是使用的场合和方式有所不同。都是一种用于创建快速动态网页的技术 1、认识同步请求和异步请求&#xff1f; 1.1、认识同步请求&#xff1f; 1、我们点击淘宝首页的男装&#xff0c;进入男装页面的这…

vue3+vite+ts项目打包时出错

项目中引入了element-plus国家化的配置&#xff0c;然后进行项目打包&#xff0c;报下面的错误 解决方法&#xff1a; 在main.ts中添加 // ts-ignore

Ubuntu 22.04安装Go 1.21.4编译器

lsb_release -r看到操作系统版本是22.04,uname -r看到内核版本是uname -r。 sudo wget https://studygolang.com/dl/golang/go1.21.4.linux-amd64.tar.gz下载编译器。 sudo tar -zxf go1.21.4.linux-amd64.tar.gz -C /goroot将文件解压到/goroot目录下&#xff0c;这个命令…

基于多模态大数据的国家安全风险态势感知模型构建

源自&#xff1a;情报杂志 “人工智能技术与咨询” 发布 摘要 [研究目的]为强化国家安全情报能力,推动风险监测预警能力提升,构建基于多模态大数据的国家安全风 险态势感知模型。 [研究方法]首先,对国家安全风险态势感知进行阐释;然后,分析多模态大数据驱动下…

JSP forEach标签遍历 java bean类型的list集合

好 之前我讲了 forEach 标签 但只是说了基本的使用 但我们实际开发中 还是循环遍历对象数组最多 就是一个java bean类型的list集合 那么 首先 我们要提供一个java bean 我们在java目录下 创建一个目录 我这里叫 attribute 下面创建一个类 叫users 参考代码如下 package com.e…