基于DUP的网络聊天室

news2024/11/15 19:57:15

基于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;
}

结果

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

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

相关文章

C++:基于C的语法优化

C&#xff1a;基于C的语法优化 命名空间命名空间域域作用限定符展开命名空间域 输入输出缺省参数全缺省参数半缺省参数 函数重载参数类型不同参数个数不同参数类型的顺序不同 引用基本语法按引用传递返回引用引用与指针的区别 内联函数autoauto与指针和引用结合 范围for循环nul…

统计灰度图像的灰度值分布并绘制

1、numpy方法 函数&#xff1a; numpy.histogram(a, bins10, rangeNone, normedNone, weightsNone, densityNone) 参数说明&#xff1a; a:输入数据数组&#xff1b;bins:指定统计的区间个数&#xff0c;可以是一个整数&#xff0c;也可以是一个数组&#xff0c;默认值为10…

续签KES证书

MiniO KES&#xff08;密钥加密服务&#xff09;是 MinIO 开发的一项服务&#xff0c;旨在弥合在 Kubernetes 中运行的应用程序与集中式密钥管理服务 &#xff08;KMS&#xff09; 之间的差距。中央 KMS 服务器包含所有状态信息&#xff0c;而 KES 在需要执行与获取新密钥或更新…

最小生成树(Java实现)

一、Prim算法 Prim算法基本思想为&#xff1a;从联通网络 N{V,E}中某一顶点 v0 出发&#xff0c;此后就从一个顶点在 S 集中&#xff0c; 另一个顶点不在 S 集中的所有顶点中选择出权值最小的边&#xff0c;把对应顶点加入到 S 集 中&#xff0c; 直到所有的顶点都加入到 S 集中…

RK3568平台 TinyAlsa集成第三方音频算法

一.tinyalsa介绍 ALSA&#xff08;Advanced Linux Sound Architecture&#xff09;是一个开源项目&#xff0c;涵盖了用户空间和内核空间对音频设备的操作接口&#xff0c;通过应用层使用alsalib可以实现对音频设备的控制 TinyAlsa是android推出的一个精简的ALSA库&#xff0c…

【Web实操08】实现一个导航效果,要求横向摆放,并且清除浮动

要实现图片的效果&#xff1a; 要利用浮动的知识点完成首页&#xff0c;电视&#xff0c;平板&#xff0c;家电&#xff0c;服务在一行导航栏剧中居中显示的功能&#xff0c;背景设置为灰黑色&#xff0c;导航栏下面是内容。 代码如下&#xff1a; <!DOCTYPE html> &l…

flink学习之窗口处理函数

窗口处理函数 什么是窗口处理函数 Flink 本身提供了多层 API&#xff0c;DataStream API 只是中间的一环&#xff0c;在更底层&#xff0c;我们可以不定义任何具体的算子&#xff08;比如 map()&#xff0c;filter()&#xff0c;或者 window()&#xff09;&#xff0c;而只是…

springboot集成COS对象存储

1.申请腾讯云存储桶 新建密钥&#xff08;后面配置要用到&#xff09; 2.编写工具类 此处使用工具类进行基本属性配置&#xff0c;也可选择在yml中配置 package com.sfy.util;import com.qcloud.cos.COSClient; import com.qcloud.cos.ClientConfig; import com.qcloud.cos.a…

开源堡垒机JumpServer本地安装并配置公网访问地址

文章目录 前言1. 安装Jump server2. 本地访问jump server3. 安装 cpolar内网穿透软件4. 配置Jump server公网访问地址5. 公网远程访问Jump server6. 固定Jump server公网地址 前言 JumpServer 是广受欢迎的开源堡垒机&#xff0c;是符合 4A 规范的专业运维安全审计系统。JumpS…

计算机服务器中了mallox勒索病毒怎么办,mallox勒索病毒解密数据恢复

企业的计算机服务器存储着企业重要的信息数据&#xff0c;为企业的生产运营提供了极大便利&#xff0c;但网络安全威胁随着技术的不断发展也在不断增加&#xff0c;近期&#xff0c;云天数据恢复中心接到许多企业的求助&#xff0c;企业的计算机服务器中了mallox勒索病毒&#…

IDEA2023.2 将普通项目转Maven项目

1、选中一个普通工程&#xff1a; 2、快捷键&#xff1a;ctrlshift a&#xff0c;搜索&#xff1a;Add Framework Support… 3、勾选maven&#xff0c;点击ok。

谁适合选择虚拟化

情况 前些天,有人问弄虚拟化怎么样: 还有一个群里,讨论了这事: 也弄了很多年了,虽然不算深入,毕竟,也是拼尽了全力,毕竟差不多7年的时光已经投入进去了,回头时,感觉没留下什么,有些十年技术一场空的感觉,真是应了虚拟化这几个字。 现在就大体说说这事: 先看看当前…

网络通信(Socket/TCP/UDP)

一、Socket 1.概念: Socket(又叫套接字)是通信的基石,是支持TCP/IP协议的网络通信的基本操作单元。它是网络通信过程中端点的抽象表示,包含进行网络通信必须的五种信息:连接协议,客户端的IP地址,客户端的端口,服务器的IP地址,服务器的端口。 一个Socket是一对IP地址…

DP专题17 单词拆分

本题链接&#xff1a;力扣&#xff08;LeetCode&#xff09;官网 - 全球极客挚爱的技术成长平台 题目&#xff1a; 思路&#xff1a; 由题意&#xff0c;根据题目意思&#xff0c;给出字符串 S&#xff0c;以及一个字符串数组&#xff0c;问字符串数组中 是否可以任取字符…

java中stream流进行遍历

在源代码转向加工到目标代码时&#xff0c;可以使用加工流代码加工 三种方式&#xff1a; 1.使用stream流的of方法 Stream.of(arr); 2.使用数组的Arrays.stream Arrays.stream(arr); 3.集合类&#xff0c;继承了Collection的.stream List<Strin…

2.2.1.1-一个关于定投的故(姿)事(势)

跳转到根目录&#xff1a;知行合一&#xff1a;投资篇 已完成&#xff1a; 1、投资&技术   1.1.1 投资-编程基础-numpy   1.1.2 投资-编程基础-pandas   1.2 金融数据处理   1.3 金融数据可视化 2、投资方法论   2.1.1 预期年化收益率   2.1.2 一个关于yaxb的…

工业相机+镜头选型及靶面、焦距计算等相关详解

工业相机镜头选型及靶面、焦距计算等相关详解 着重讲述相机的各个参数及使用意义总结相机镜头选型主要参数的推理计算 0. 工业相机相关概念简介 相机与镜头一览 工业相机与镜头实物图如下图所示&#xff1a; 常见的相机有两种供电方式&#xff1a;一种是电源线供电&#xff0…

码农维权——案例分析之违法解除劳动合同(二)

目录 一、背景 二、案例来源 三、被【非法】解除《劳动合同》后可以主张哪些诉求&#xff1f; 四、案例分析&#xff1a;违法解除劳动合同 A、公司的主张&#xff1a; B、公司的主要证据&#xff08;公司单方面提交的&#xff0c;法院不一定认可采纳&#xff09;&…

QT的绘图系统QPainterDevice与文件系统QIODevice

QT的绘图系统&#xff08;QPainterDevice&#xff09;与文件系统&#xff08;QIODevice&#xff09; 文章目录 1、Qt 的绘图系统1、QPainter的使用2、QPen(画笔&#xff09;及QBursh&#xff08;画刷&#xff09;3、手动更新窗口4、绘图设备1、四种绘图设备的 区别2、 QBitmap3…

革新区块链:代理合约与智能合约升级的未来

作者 张群&#xff08;赛联区块链教育首席讲师&#xff0c;工信部赛迪特聘资深专家&#xff0c;CSDN认证业界专家&#xff0c;微软认证专家&#xff0c;多家企业区块链产品顾问&#xff09;关注张群&#xff0c;为您提供一站式区块链技术和方案咨询。 代理合约&#xff08;Prox…