项目:基于UDP的网络聊天室

news2024/11/25 0:07:04

项目需求:
1.如果有用户登录,其他用户可以收到这个人的登录信息
2.如果有人发送信息,其他用户可以收到这个人的群聊信息
3.如果有人下线,其他用户可以收到这个人的下线信息
4.服务器可以发送系统信息

服务器代码:

#include <myhead.h>
typedef struct group
{
	char type;
	char name[20];
	char text[128];
}gp_t;

typedef struct Node
{
	int PORT;
	struct Node* next;
}*Linklist;

Linklist create_node()
{
	Linklist s=(Linklist)malloc(sizeof(struct Node));
	if(NULL == s)
		return NULL;
	s->PORT =0;
	s->next =NULL;
	return s;
}

Linklist insert_rear(Linklist head,int element)
{
	Linklist s=create_node();
	s->PORT=element;

	if(NULL == head)
	{
		head = s;
		return head;
	}
	Linklist p = head;
	while(p->next != NULL)
	{
		p=p->next;
	}
	p->next = s;
	return head;
}



int lenth(Linklist head)
{
	if(head == NULL)
		return 0;
	int count=0;
	Linklist p=head;
	while(p!=NULL)
	{
		count++;
		p=p->next;
	}
	free(p);
	p=NULL;
	return count;
}

int find_element(Linklist head,int element)
{
	Linklist p=head;
	for(int i=0;i<lenth(head);i++)
	{
		if(p->PORT == element)
			return i;
		p=p->next;
	}
}

Linklist del_head(Linklist head)
{
	if(head->next == NULL)
	{
		free(head);head=NULL;
		return head;
	}
	Linklist del=head->next;
	head->PORT=del->PORT;
	head->next=del->next;
	free(del);del=NULL;
	return head;
}

Linklist del_rear(Linklist head)
{
	if(head->next == NULL)
	{
		free(head);
		head = NULL;
		return head;
	}
	Linklist del=head;
	while(del->next->next!=NULL)
	{
		del=del->next;
	}
	free(del->next);
	del->next=NULL;
	return head;
}

Linklist del_pos(Linklist head,int pos)
{
	if(pos == lenth(head)-1)
	{
		head = del_rear(head);
		return head;
	}
	else if(pos == 0)
	{
		head = del_head(head);
		return head;
	}
	else
	{
		Linklist p=head;
		for(int i=0;i<pos-1;i++)
		{
			p=p->next;
		}
		Linklist r=p->next;
		p->next=r->next;
		free(r);
		r=NULL;
		return head;
	}
}

Linklist del(Linklist head,int element)
{
	if(head ==NULL)
		return head;
	int pos = find_element(head,element);
	head = del_pos(head,pos);
	return head;

}

int main(int argc, const char *argv[])
{
	if(argc != 3)
	{
		printf("请输入服务器IP和端口号!\n");
		return -1;
	}

	int sfd = socket(AF_INET,SOCK_DGRAM,0);
	if(sfd == -1)
	{
		perror("socket error");
		return -1;
	}
	
	struct sockaddr_in sin;
	sin.sin_family = AF_INET;
	sin.sin_port = htons(atoi(argv[2]));
	sin.sin_addr.s_addr = inet_addr(argv[1]);

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

	struct sockaddr_in cin;
	cin.sin_family = AF_INET;
	socklen_t socklen = sizeof(cin);

	Linklist Usr_PORT=NULL;
	gp_t usr;
	char buf[149] = "";
	char rbuf[130] = "";
	struct pollfd fds[2];
	fds[0].fd = 0;
	fds[0].events = POLLIN;
	fds[1].fd = sfd;
	fds[1].events = POLLIN;
	int res = 0;  //接收select的返回值

	while(1)
	{
		res = poll(fds,2,-1);
		if(res == -1)
		{
			perror("poll error");
			return -1;
		}
		else if(res == 0)
		{
			printf("time out");
			return -1;
		}
	
		bzero(buf,sizeof(buf));

		if(fds[0].revents == POLLIN)
		{
			strcpy(buf,"system:");
			fgets(buf+7,sizeof(buf)-7,stdin);
			buf[strlen(buf)-1] = '\0';
			Linklist p = Usr_PORT;
			while(p!= NULL)
			{
				cin.sin_port = htons(p->PORT);
				sendto(sfd,buf,sizeof(buf),0,(struct sockaddr*)&cin,sizeof(cin));
				p=p->next;
			}
		}

		if(fds[1].revents == POLLIN)
		{
			
			recvfrom(sfd,&usr,sizeof(usr),0,(struct sockaddr*)&cin,&socklen);
			if(usr.type == 'L')
			{
				Usr_PORT = insert_rear(Usr_PORT,ntohs(cin.sin_port));
			
				printf("[%s:%d]已经上线\n",usr.name,ntohs(cin.sin_port));
				sprintf(buf,"-----%s已经上线-----",usr.name);
				printf("buf = %s\n",buf);
				Linklist p = Usr_PORT;
				while(p->next!= NULL)
				{
					cin.sin_port = htons(p->PORT);

					sendto(sfd,buf,sizeof(buf),0,(struct sockaddr*)&cin,sizeof(cin));
					p=p->next;
				}
			}
			else if(usr.type == 'C')
			{
				sprintf(buf,"%s:%s",usr.name,usr.text);

				Linklist p = Usr_PORT;
				int NONE=ntohs(cin.sin_port);
				while(p!= NULL)
				{
					if(NONE!=p->PORT)
					{
						cin.sin_port = htons(p->PORT);
						sendto(sfd,buf,sizeof(buf),0,(struct sockaddr*)&(cin),sizeof(cin));
					}
					p=p->next;
				}
			}
			else if(usr.type == 'Q')
			{
				sprintf(buf,"-----%s已经下线-----",usr.name);
				printf("[%s:%d]已经离线\n",usr.name,ntohs(cin.sin_port));
				Usr_PORT = del(Usr_PORT,ntohs(cin.sin_port));
				Linklist p = Usr_PORT;
				while(p!= NULL)
				{
					cin.sin_port = htons(p->PORT);
					sendto(sfd,buf,sizeof(buf),0,(struct sockaddr*)&cin,sizeof(cin));
					p=p->next;
				}
			}
		}
	}
	close(sfd);
	return 0;
}

客户端代码:

#include <myhead.h>

typedef struct
{
	char type;
	char name[20];
	char text[128];
}gp_t;

int main(int argc, const char *argv[])
{
	if(argc != 3)
	{
		printf("请输入服务器IP和端口号!\n");
		return -1;
	}

	int cfd = socket(AF_INET,SOCK_DGRAM,0);
	if(cfd == -1)
	{
		perror("socket error");
		return -1;
	}

	gp_t GP;
	char name[20] = "";
	printf("请输入用户名>>");
	scanf("%s",GP.name);
	getchar();

	struct sockaddr_in sin;
	sin.sin_family = AF_INET;
	sin.sin_port = htons(atoi(argv[2]));
	sin.sin_addr.s_addr = inet_addr(argv[1]);

	char buf[130] = "";
	char rbuf[128] = "";

	bzero(buf,sizeof(buf));
	GP.type = 'L';
	sendto(cfd,&GP,sizeof(GP),0,(struct sockaddr*)&sin,sizeof(sin));

	struct pollfd fds[2];
	fds[0].fd = 0;
	fds[0].events = POLLIN;

	fds[1].fd = cfd;
	fds[1].events = POLLIN;
	int res = 0;

	while(1)
	{
		res = poll(fds,2,-1);
		if(res == -1)
		{
			perror("poll error");
			return -1;
		}
		else if(res == 0)
		{
			printf("time out\n");
			return -1;
		}

		bzero(buf,sizeof(buf));
		bzero(rbuf,sizeof(rbuf));

		if(fds[1].revents == POLLIN)
		{
			recvfrom(cfd,rbuf,sizeof(rbuf),0,NULL,NULL);
			printf("%s\n",rbuf);
		}

		if(fds[0].revents == POLLIN)
		{
			fgets(GP.text,sizeof(GP.text),stdin);
			GP.text[strlen(GP.text)-1]='\0';

			if(strcmp(GP.text,"quit")==0)
			{
				GP.type = 'Q';
				sendto(cfd,&GP,sizeof(GP),0,(struct sockaddr*)&sin,sizeof(sin));
				goto A;
			}
			GP.type = 'C';
			sendto(cfd,&GP,sizeof(GP),0,(struct sockaddr*)&sin,sizeof(sin));
		}
	}
A:
	close(cfd);
	return 0;
}

在这里插入图片描述

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

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

相关文章

深入了解Java8新特性-日期时间API:LocalDateTime类

阅读建议 嗨&#xff0c;伙计&#xff01;刷到这篇文章咱们就是有缘人&#xff0c;在阅读这篇文章前我有一些建议&#xff1a; 本篇文章大概22000多字&#xff0c;预计阅读时间长需要20分钟以上。本篇文章的实战性、理论性较强&#xff0c;是一篇质量分数较高的技术干货文章&…

离散数学-集合论基础

3.1集合的基本概念 1&#xff09;集合及元素 2&#xff09;集合的表示 3&#xff09;集合的关系 4&#xff09;特殊集合 3.2集合的运算 并、交、差、对称差 3.3集合的划分与覆盖 3.4排斥包含管理 3.1集合的基本概念 1&#xff09;集合及元素 将某种具有同种属性的个体…

记录Windows下安装redis的过程

开源博客项目Blog支持使用EasyCaching组件操作redis等缓存数据库&#xff0c;在继续学习开源博客项目Blog之前&#xff0c;准备先学习redis和EasyCaching组件的基本用法&#xff0c;本文记录在Windows下安装redis的过程。   虽然redis官网文档写着支持Linux、macOS、Windows等…

pyecharts绘制自定义点+连线取消箭头+时间帧叠加

pyecharts之Geo地图大法&#xff08;详解&#xff0c;代码带注释效果图&#xff09; 近期项目上有地图自定义绘点连线分严重等级的需求&#xff0c;整了&#xff0c;分开处理啥都好说&#xff0c;多个数据放在同一维度的时候&#xff0c;只恨pyecharts的开发者为什么把功能整得…

简介vue

目录 一、介绍 渐进式框架​ 单文件组件​ 选项式 API (Options API)​ 组合式 API (Composition API)​ 该选哪一个&#xff1f;​ 创建一个 Vue 应用 应用实例​ 根组件​ DOM 中的根组件模板 应用配置​ 多个应用实例​ 一、介绍 Vue (发音为 /vjuː/&#xff…

Selenium 学习(0.17)——软件测试之测试用例设计方法——白盒测试——逻辑覆盖法(条件覆盖和条件判定覆盖)

条件覆盖 设计测试用例&#xff0c;使每个判断中每个条件的可能取值至少满足一次。 条件判定覆盖 通过设计足够的测试用例&#xff0c;满足如下条件&#xff1a; 所有条件的可能至少执行一次的取值 所有判断的可能结果至少执行一次 条件判定覆盖同时满足判定覆…

灰度发布专题---3、Nginx+Lua灰度发布

上一章已经讲解了配置文件灰度发布、应用版本灰度发布、API网关灰度发布实现&#xff0c;但如果用户这时候在代理层如何做灰度发布呢&#xff1f; 代理层灰度发布分析 用户无论访问应用服务还是静态页&#xff0c;都要经过Nginx代理层&#xff0c;我们可以在Nginx这里做灰度发…

读像火箭科学家一样思考笔记12_实践与测试(下)

1. 舆论的火箭科学 1.1. 如果苹果违反了“即飞即测”原则&#xff0c;那苹果的iPhone就不会问世了 1.1.1. iPhone在其上市前的民意调查中相当失败 1.1.1.1. iPhone不可能获得太大市场份额&#xff0c;不可能。 1.1.1.1.1. 微软前CEO史蒂夫鲍尔默&#xff08;Steve Ballmer&…

AIGC系列之:GroundingDNIO原理解读及在Stable Diffusion中使用

目录 1.前言 2.方法概括 3.算法介绍 3.1图像-文本特征提取与增强 3.2基于文本引导的目标检测 3.3跨模态解码器 3.4文本prompt特征提取 4.应用场景 4.1结合生成模型完成目标区域生成 4.2结合stable diffusion完成图像编辑 4.3结合分割模型完成任意图像分割 1.前言 …

第20章 多线程

创建线程 继承Thread 类 Thread 类时 java.lang 包中的一个类&#xff0c;从类中实例化的对象代表线程&#xff0c;程序员启动一个新线程需要建立 Thread 实例。 Thread 对象需要一个任务来执行&#xff0c;任务是指线程在启动时执行的工作&#xff0c;start() 方法启动线程…

第一百八十二回 自定义一个可以滑动的刻度尺

文章目录 1. 概念介绍2. 思路与方法2.1 实现思路2.2 实现方法3. 示例代码4. 内容总结我们在上一章回中介绍了"如何绘制阴影效果"相关的内容,本章回中将介绍 如何自定义一个可以滑动的刻度尺.闲话休提,让我们一起Talk Flutter吧。 1. 概念介绍 任何优美的文字在图…

[SaaS] 广告创意中stable-diffusion的应用

深度对谈&#xff1a;广告创意领域中 AIGC 的应用这个领域非常快速发展&#xff0c;所以你应该保持好奇心&#xff0c;不断尝试新事物&#xff0c;不断挑战自己。https://mp.weixin.qq.com/s/ux9iEABNois3y4wwyaDzAQ我对AIGC领域应用调研&#xff0c;除了MaaS服务之外&#xff…

电荷泵升压/降压电路

一、升压\降压电路原理分析 1、升压电路 电荷泵升压电路 VoutVa5V 5V_PLUS0V时&#xff0c;Va给C2充电&#xff0c;C2上节点电压比C2下节点电压高Va&#xff1b; 5V_PLUS5V时&#xff0c;C2电压不能突变&#xff0c;C2上节点电压依然比C2下节点电压高Va&#xff0c;但C2下节点…

supermap-iserver激活教程(linux)

本篇只介绍linux临时许可激活教程&#xff0c;windows的原理一摸一样不做赘述。 1.下载许可中心&#xff08;web版&#xff09; SuperMap技术资源中心|为您提供全面的在线技术服务 2.解压 supermap-bslicense-server-3.0.24-linux-x64.tar.gz tar -zxvf supermap-bslicense…

选择排序以及改进方案

选择排序以及改进方案 介绍&#xff1a; 选择排序是一种简单直观的排序算法&#xff0c;它的基本思想是在未排序序列中选择最小&#xff08;或最大&#xff09;的元素&#xff0c;然后将其放在已排序序列的末尾。选择排序的过程就像是每次从待排序的元素中选择最小的一个&…

Java基于ssm的租房求租网站房东直租中介托管房屋出租项目源码

演示视频 https://www.bilibili.com/video/BV1Lh411J7ic/?share_sourcecopy_web&vd_source11344bb73ef9b33550b8202d07ae139b 可转成springboot项目。 主要功能&#xff1a;租户可以浏览搜索收藏房源&#xff0c;预约看房&#xff0c;发布求租信息。房东可以发布管理房源…

2023-11-28-直播单细胞图表美化-seurat数据结构 featureplot dotplot vlnplot

单细胞常见的可视化方式有DimPlot&#xff0c;FeaturePlot &#xff0c;DotPlot &#xff0c;VlnPlot 和 DoHeatmap几种 &#xff0c;Seurat中均可以很简单的实现&#xff0c;但是文献中的图大多会精美很多。 之前 跟SCI学umap图| ggplot2 绘制umap图&#xff0c;坐标位置 &am…

SSL证书实惠品牌——JoySSL

随着互联网的普及和发展&#xff0c;网络安全问题日益严重。为了保护网站数据的安全&#xff0c;越来越多的网站开始使用SSL证书。JoySSL证书作为一款高性价比的SSL证书&#xff0c;受到了广泛的关注和好评。 目前市面上主流的证书基本上都是国外证书&#xff0c;也就是说你在验…

【用unity实现100个游戏之17】从零开始制作一个类幸存者肉鸽(Roguelike)游戏4(附项目源码)

文章目录 本节最终效果前言命中敌人闪白和击退效果敌人死亡效果等级 击杀数 经验绘制经验条显示等级和杀敌数游戏倒计时玩家血条参考源码完结 本节最终效果 前言 本节紧跟着上一篇&#xff0c;主要实现敌人受击死亡效果特效&#xff0c;主角等级、击杀数、经验、血条UI显示。 …

C# datagridview控件 绑定数据库中表中数据的方式-3

1.如下图所示&#xff0c;为数据库中的一张表结构&#xff0c;注意该表中共有11个字段 2.首先在窗体后台代码中拖入一个datagridview控件&#xff0c;并在窗体加载时&#xff0c;给datagridview控件添加列&#xff0c;添加的方式如下所示&#xff1a;请注意&#xff0c;每个列…