UDP实现群聊通信

news/2024/5/18 13:16:48 标签: udp, 网络协议, 网络

服务器端

#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.niftyadmin.cn/n/5224985.html

相关文章

零基础可以学编程吗,不懂英语怎么学编程,中文编程工具实例

零基础可以学编程吗&#xff0c;不懂英语怎么学编程&#xff0c;中文编程工具实例 上图是中文编程工具界面、标尺实例。 给大家分享一款中文编程工具&#xff0c;零基础轻松学编程&#xff0c;不需英语基础&#xff0c;编程工具可下载。 这款工具不但可以连接部分硬件&#x…

智能优化算法应用:基于回溯搜索算法无线传感器网络(WSN)覆盖优化 - 附代码

智能优化算法应用&#xff1a;基于回溯搜索算法无线传感器网络(WSN)覆盖优化 - 附代码 文章目录 智能优化算法应用&#xff1a;基于回溯搜索算法无线传感器网络(WSN)覆盖优化 - 附代码1.无线传感网络节点模型2.覆盖数学模型及分析3.回溯搜索算法4.实验参数设定5.算法结果6.参考…

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

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

​LeetCode解法汇总2336. 无限集中的最小数字

目录链接&#xff1a; 力扣编程题-解法汇总_分享记录-CSDN博客 GitHub同步刷题项目&#xff1a; https://github.com/September26/java-algorithms 原题链接&#xff1a;力扣&#xff08;LeetCode&#xff09;官网 - 全球极客挚爱的技术成长平台 描述&#xff1a; 现有一个包…

【领域驱动设计 学习目标及大纲】从CRUD到架构设计

从2018年至今&#xff0c;已工作了5年有余&#xff0c;回望这5年的工作历程&#xff0c;虽然一直在学习、一直在积累&#xff0c;但其实都在术的层面上停留&#xff0c;也就是具体的技术点。这5年多的时间里其实也不是没有窥道的想法&#xff1a; 一次是2018年刚工作的时候&am…

供应链 | “利刃出鞘”——顶刊POMS论文解读:制造商借助电子商务部门入侵

论文解读者&#xff1a;肖善&#xff0c;温梓曦&#xff0c;张怡雯&#xff0c;杨子豪 编者按&#xff1a; 解密品牌商在线电商平台&#xff1a;组织结构、策略选择、三方共赢 Manufacturer encroachment with an e‐commerce division 原文作者信息 Shi, S., Wang, C., Ch…

手把手教你Autodl平台Qwen-7B-Chat FastApi 部署调用

手把手带你在AutoDL上部署Qwen-7B-Chat FastApi 调用 项目地址&#xff1a;https://github.com/datawhalechina/self-llm.git 如果大家有其他模型想要部署教程&#xff0c;可以来仓库提交issue哦~ 也可以自己提交PR&#xff01; 如果觉得仓库不错的话欢迎star&#xff01;&…

视频素材传输慢?大文件传输软件一步到位

视频素材在视频制作和发布中具有举足轻重的地位。无论是拍摄、剪辑、添加特效还是配音&#xff0c;都需要涉及原始或经过处理的视频素材。然而&#xff0c;视频素材的传输却经常被忽视&#xff0c;却又是一个至关重要的环节。 传统的文件传输方式&#xff0c;如邮件、网盘、U盘…