项目篇:基于UDP通信模型的网络聊天室

思维导图

基于UDP通信模型的网络聊天室

消息分类及数据包结构

服务器端

#include <head.h>
#define SER_PORT 8888
#define SER_IP "192.168.232.133"
typedef struct mb
{
	struct sockaddr_in cin;
	char name[20];
	struct mb *next;
}*member;
//群发消息
int send_to_all(int sfd,member head,const char *buf,size_t length)
{
	member p=head;
	while(p!=NULL)
	{
		sendto(sfd,buf,length,0,(struct sockaddr*)&(p->cin),sizeof(p->cin));
		p=p->next;
	}
	return 0;
}
//增加成员
member add_member(member head,const char *data,struct sockaddr_in cin)
{
	member p=(member)malloc(sizeof(struct mb));
	p->cin=cin;
	strcpy(p->name,data);
	p->next=head;
	head=p;
	return head;
}
//删除成员
member del_member(member head,const char *name_point)
{
	member p=head;
	if(strcmp(p->name,name_point)==0)
	{
		head=p->next;
		free(p);
		p=NULL;
		return head;
	}
	while(strcmp(p->name,name_point)!=0)
	{
		p=p->next;
	}
	if(p->next==NULL)
	{
		member q=head;
		while(q->next->next!=NULL)
		{
			q=q->next;
		}
		free(p);
		p=NULL;
		q->next=NULL;
		return head;
	}
	member q=head;
	while(strcmp(q->next->name,name_point)!=0)
	{
		q=q->next;
	}
	q->next=p->next;
	free(p);
	p=NULL;
	return head;
}



int main(int argc, const char *argv[])
{

	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(SER_PORT);
	sin.sin_addr.s_addr=inet_addr(SER_IP);
	if(bind(sfd,(struct sockaddr*)&sin,sizeof(sin))==-1)
	{
		perror("bind error:");
		return -1;
	}
	struct sockaddr_in cin;
	socklen_t socklen=sizeof(cin);
	printf("bind success\n");

	struct pollfd pfd[1024];
	pfd[0].fd=0;
	pfd[0].events=POLLIN;
	pfd[1].fd=sfd;
	pfd[1].events=POLLIN;
	int n=2;
	member head=NULL;

	while(1)
	{
		int res=poll(pfd,n,-1);
		if(res==-1)
		{
			perror("poll error:");
			return -1;
		}
		else if(res==0)
		{
			printf("manbaout\n");
			return -1;
		}
		if(pfd[0].revents==POLLIN)
		{
			//系统发送消息
			char buf[128]="";
			scanf("%s",buf);
			char sys_buf[200];
			sprintf(sys_buf,"***system***>>>%s",buf);
			send_to_all(sfd,head,sys_buf,sizeof(sys_buf));
			printf("系统发送消息\n");
		}
		if(pfd[1].revents==POLLIN)
		{
			//接收消息
			char buf[200]="";
			recvfrom(pfd[1].fd,buf,sizeof(buf),0,(struct sockaddr*)&cin,&socklen);
			short *type_point = (short*)buf;
			switch(ntohs(*type_point))
			{
			case 1:
				{
					//接收到登录的消息
					char *data_point = buf+2;
					char buf[300]="";
					sprintf(buf,"**********%s已登录**********",data_point);
					send_to_all(sfd,head,buf,sizeof(buf));
					head=add_member(head,data_point,cin);
					printf("%s登录\n",data_point);
					break;
				}
			case 2:
				{
					//接收到普通的消息
					char *name_point=buf+2;
					char *data_point=name_point+strlen(name_point)+1;
					char buf[300]="";
					sprintf(buf,"%s>>>%s",name_point,data_point);
					send_to_all(sfd,head,buf,sizeof(buf));
					printf("%s发送消息\n",name_point);
					break;
				}
			case 3:
				{
					//接收到退出消息
					char *name_point=buf+2;
					char *data_point=name_point+strlen(name_point)+1;
					char endbuf[20]="";
					strcpy(endbuf,"quit");
					sendto(sfd,endbuf,sizeof(endbuf),0,(struct sockaddr*)&cin,sizeof(cin));
					del_member(head,name_point);
					char buf[300]="";
					sprintf(buf,"**********%s已下线**********",name_point);
					send_to_all(sfd,head,buf,sizeof(buf));
					printf("%s下线\n",name_point);
					break;
				}
			}
		}
	}
	close(sfd);
	return 0;
}

客户端

#include <head.h>
#define SER_PORT 8888
#define SER_IP "192.168.232.133"

int login(int sfd,struct sockaddr_in sin,const char *name)
{
	
	char buf[200]="";
	short *type_point = (short*)buf;
	char *data_point = buf+2;
	*type_point=htons(1);
	strcpy(data_point,name);

	sendto(sfd,buf,sizeof(buf),0,(struct sockaddr*)&sin,sizeof(sin));
	return 0;
}
int main(int argc, const char *argv[])
{
	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(SER_PORT);
	sin.sin_addr.s_addr=inet_addr(SER_IP);
	socklen_t socklen;

	printf("====================欢迎使用网络聊天室====================\n");
	printf("请输入姓名:");
	char name[20];
	scanf("%s",name);

	login(sfd,sin,name);
	
	pid_t pid;
	pid=fork();
	if(pid>0)
	{
		//父进程,用于发消息
		char buf[128]="";
		short *type_point = (short*)buf;
		char *name_point = buf+2;
		strcpy(name_point,name);
		char *data_point=name_point+strlen(name_point)+1;
		while(1)
		{
			scanf("%s",data_point);
			if(strcmp(data_point,"quit")==0)
			{
				*type_point=htons(3);
				sendto(sfd,buf,sizeof(buf),0,(struct sockaddr*)&sin,sizeof(sin));
				break;
			}
			*type_point=htons(2);
			sendto(sfd,buf,sizeof(buf),0,(struct sockaddr*)&sin,sizeof(sin));
		}
	}
	else if(pid==0)
	{
		//子进程,用于接收消息
		while(1)
		{
			char buf[128];
			recvfrom(sfd,buf,sizeof(buf),0,(struct sockaddr*)&sin,&socklen);
			if(strcmp(buf,"quit")==0)
			{
				break;
			}
			printf("%s\n",buf);
		}
	}

	wait(NULL);
	close(sfd);
	return 0;
}

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

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

相关文章

【英文干货】【Word_Search】找单词游戏(第1天)

本期主题&#xff1a;Mindfulness&#xff08;意识力&#xff09; 本期单词&#xff1a; Awareness 意识 Breathing 呼吸 Calm 平静的 De-Stress 减压 Feelings 感受&#xff0c;情感 Inspection 调查 Meditation 冥想 Peace 和平 Quiet 安静的 Recollection 回忆 R…

当世界加速离你而去

当世界加速离你而去 会不会这个标题显的太悲观&#xff0c;也可能是耳机里正在放着To Be Frank的原因。 对于阳历跨年我是没有太多的感觉&#xff0c;而且跨年夜忙着约会&#xff0c;所以2023年的跨年文章今天才出来。 一年的时间一晃就过了。2022年12月9日时候彻底结束了风控…

ELK 分离式日志(1)

目录 一.ELK组件 ElasticSearch&#xff1a; Kiabana&#xff1a; Logstash&#xff1a; 可以添加的其它组件&#xff1a; ELK 的工作原理&#xff1a; 二.部署ELK 节点都设置Java环境: 每台都可以部署 Elasticsearch 软件&#xff1a; 修改elasticsearch主配置文件&…

FOR XML PATH 函数与同一分组下的字符串拼接

FOR XML PATH 简单介绍 FOR XML PATH 语句是将查询结果集以XML形式展现&#xff0c;通常情况下最常见的用法就是将多行的结果&#xff0c;拼接展示在同一行。 首先新建一张测试表并插入数据&#xff1a; CREATE TABLE #Test (Name varchar(70),Hobby varchar(70) );insert #T…

EHS管理系统为何需要物联网的加持?

EHS是Environment、Health、Safety的缩写&#xff0c;是从欧美企业引进的管理体系&#xff0c;在国外也被称为HSE。EHS是指健康、安全与环境一体化的管理。 而在国内&#xff0c;整个EHS市场一共被分成三类&#xff1b; 一类是EHS管培体系&#xff0c;由专门的EHS机构去为公司…

Watch(监视器)+(综合案例)

Watch侦听器&#xff08;监视器&#xff09; 作用&#xff1a;监视数据变化&#xff0c;执行一些业务逻辑或异步操作 语法&#xff1a; ①简单写法 → 简单类型数据&#xff0c;直接监视 ②完整写法 → 添加额外配置项 ①简单写法 <!DOCTYPE html> <html lang"…

CLion调试Nodejs源码

【环境】 macOS node-v20.11.0源码 CLion 2023.3.2 【1】下载源码 https://nodejs.org/en/download/ 【2】编译源码 解压后的目录如下 进入解压后的目录进行编译 ./configure --debug make -C out BUILDTYPEDebug -j 4需要好久… 编译成功之后在node-v20.11.0目录下会有一个…

DALL·E 3功能:开启创意无限的新纪元

在人工智能的黄金时代&#xff0c;MidTool以其DALLE 3功能引领了一个全新的创意革命。这项技术不仅仅是一个简单的图像生成工具&#xff0c;它是一种将想象力转化为视觉现实的魔法。在这篇文章中&#xff0c;我们将深入探讨MidTool的DALLE 3功能&#xff0c;并揭示它如何成为艺…

三、MySQL之创建和管理表

一、基础知识 1.1 一条数据存储的过程 存储数据是处理数据的第一步 。只有正确地把数据存储起来,我们才能进行有效的处理和分析。否则,只 能是一团乱麻,无从下手。 在 MySQL 中, 一个完整的数据存储过程总共有 4 步,分别是创建数据库、确认字段、创建数据表、插入数据。 …

EasyDarwin计划新增将各种流协议(RTSP、RTMP、HTTP、TCP、UDP)、文件转推RTMP到其他视频直播平台,支持转码H.264、文件直播推送

之前我们尝试做过EasyRTSPLive&#xff08;将RTSP流转推RTMP&#xff09;和EasyRTMPLive&#xff08;将各种RTSP/RTMP/HTTP/UDP流转推RTMP&#xff0c;这两个服务在市场上都得到了比较多的好评&#xff0c;其中&#xff1a; 1、EasyRTSPLive用的是EasyRTSPClient取流&#xff…

技术浪潮下的程序员职业困境:一对谷歌工程师夫妻的悲剧启示

目录 前言1 裁员潮下的程序员1.1 技术变革带来的裁员潮1.2 程序员职业危机&#xff1a;技能匮乏成为致命伤 2 一对谷歌工程师夫妻的悲剧2.1 事件经过2.2 心理压力和职业困境的交织 3 技术浪潮下的程序员职业适应策略3.1 持续学习与技能更新3.2 多元化技能与职业规划3.3 职业心理…

EasyExcelFactory 导入导出功能的实战使用

EasyExcelFactory 导入导出功能的实战使用分享&#xff1a; 1、jar包引入 <!-- 阿里巴巴Excel处理--><dependency><groupId>com.alibaba</groupId><artifactId>easyexcel</artifactId><version>3.0.6</version></dependen…

2.机器学习-K最近邻(k-Nearest Neighbor,KNN)分类算法原理讲解

2️⃣机器学习-K最近邻&#xff08;k-Nearest Neighbor&#xff0c;KNN&#xff09;分类算法原理讲解 个人简介一算法概述二算法思想2.1 KNN的优缺点 三实例演示3.1电影分类3.2使用KNN算法预测 鸢(yuan)尾花 的种类3.3 预测年收入是否大于50K美元 个人简介 &#x1f3d8;️&…

华为欧拉操作系统结合内网穿透实现固定公网地址SSH远程连接

文章目录 1. 本地SSH连接测试2. openEuler安装Cpolar3. 配置 SSH公网地址4. 公网远程SSH连接5. 固定连接SSH公网地址6. SSH固定地址连接测试 欧拉操作系统(openEuler, 简称“欧拉”)是面向数字基础设施的操作系统,支持服务器、云计算、边缘openEuler是面向数字基础设施的操作系…

多线程实例练习题~

本篇文章主要是用来巩固多线程的简单应用&#xff0c;如果你已经学习了多线程的有关知识&#xff0c;想要巩固&#xff0c;那不妨拿下面几道题来考验一下自己吧&#xff01; 案例1&#xff1a;电影院售票(难度指数&#xff1a;一颗星) 题目&#xff1a;一共有1000张电影票&…

8.3 Springboot整合Redis 之Jedis方式

文章目录 前言一、Maven依赖二、新增子Module:tg-book-redis三、Jedis配置类3.1 Jedis连接池核心配置说明四、Jedis 工具类五、新增controller测试前言 Jedis是Redis官方推荐的Java客户端连接工具,用法非常简单,Jedis的API与Redis的API可以说是一模一样,所以非常有利于熟悉…

深入掌握 OSS,最完美的 OSS 上传方案!

文件上传是常见需求&#xff0c;一般我们不会把文件直接上传到应用服务器&#xff0c;因为单台服务器存储空间是有限的&#xff0c;不好扩展。 我们会用单独的 OSS &#xff08;Object Storage Service&#xff09;对象存储服务来上传下载文件。 比如一般会买阿里云的 OSS 服…

M1 MacOS下安卓虚拟化的最佳方案

categories: [VM] tags: MacOS VM 写在前面 一直想在桌面环境虚拟化安卓app, 但是看网上的推荐一直感觉不合胃口, 不是要花钱就是有广告, 想着找找开源的实现, 后来发现还是 Google 自家的产品用着舒服. 安装与配置 brew install android-studio然后随便开一个项目, 选默认…

【window】Windows11:该文件没有与之关联的应用来执行该操作

前些天发现了一个巨牛的人工智能学习网站&#xff0c;通俗易懂&#xff0c;风趣幽默&#xff0c;忍不住分享一下给大家。点击跳转到网站&#xff1a;人工智能 之前win10升级win11后&#xff0c;受不了桌面软件图标的的小箭头&#xff0c;所以弄掉了&#xff0c;但是随之而来产…

python实现带刷新的文本进度条

进度条已执行的部分使用“**”&#xff0c;未执行的部分使用“--”&#xff0c;用print&#xff08;&#xff09;来完成 使用到的函数&#xff1a; time.sleep(),作用是在程序执行过程中暂停一段时间&#xff0c;即会使程序暂停指定的秒数&#xff0c;然后再继续执行后面的代…