网络聊天室项目

服务器端

#include <myhd.h>

//传输结构体
struct cli
{
	char type;    //  L/C/Q
	char name[20];
	char text[128];
};
int main(int argc, const char *argv[])
{
	if(argc!=3)
	{
		printf("请输入ip地址和端口号\n");
		return -1;
	}
	//1、创建用于通信的套接字文件描述符
	int sfd=socket(AF_INET,SOCK_DGRAM,0);
	if(sfd==-1)
	{
		perror("socket error");
		return -1;
	}
	printf("socket success sfd=%d\n",sfd);

	//设置端口号快速重用
	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(atoi(argv[2]));
	sin.sin_addr.s_addr=inet_addr(argv[1]);
	//2.2、绑定工作
	if(bind(sfd,(struct sockaddr*)&sin,sizeof(sin))==-1)
	{
		perror("bind error");
		return -1;
	}
	printf("bind success\n");



	//填充客户端信息结构体
	struct sockaddr_in cin[1024];
	struct sockaddr_in cintemp;
	cintemp.sin_family=AF_INET;
	socklen_t socklen=sizeof(cintemp);


	//定义用于检测文件描述符的集合
	fd_set readfds,tempfds;
	//清空容器中的内容
	FD_ZERO(&readfds);
	//将要检测的文件描述符放入集合中
	FD_SET(sfd,&readfds);
	FD_SET(0,&readfds);

	//用于存放客户昵称等信息
	struct cli msg[1024];
	struct cli temp;

	//清空结构体数组
	for(int i=0;i<1024;i++)
	{
		bzero(msg[i].name,sizeof(msg[0].name));
		bzero(msg[i].text,sizeof(msg[0].text));
	}

	char buf[128]="";
	int res=0;  //接收select的返回值

	int maxi=-1;  //群聊成员个数


	while(1)
	{
		//复制一份
		tempfds=readfds;
		//使用select阻塞等待集合中的文件描述符
		res=select(sfd+1,&tempfds,NULL,NULL,NULL);
		if(res==-1)
		{
			perror("select error");
			return -1;
		}
		else if(res==0)
		{
			printf("time out\n");
			return -1;
		}
		if(FD_ISSET(sfd,&tempfds))
		{
			//清空内容
			temp.type=0;
			bzero(temp.name,sizeof(temp.name));
			bzero(temp.text,sizeof(temp.text));
			recvfrom(sfd,&temp,sizeof(temp),0,(struct sockaddr*)&cintemp,&socklen);
			if(temp.type=='l'||temp.type=='L')  //登录
			{
				printf("%s[%s:%d]:登录成功\n",temp.name,inet_ntoa(cintemp.sin_addr),ntohs(cintemp.sin_port));
				maxi++;
				strcpy(msg[maxi].name,temp.name);
				cin[maxi].sin_port=cintemp.sin_port;
				cin[maxi].sin_addr.s_addr=cintemp.sin_addr.s_addr;
				for(int j=0;j<=maxi;j++)
				{
					if(cintemp.sin_port==cin[j].sin_port)
					{
						continue;
					}
					sendto(sfd,&temp,sizeof(temp),0,(struct sockaddr*)&cin[j],sizeof(cin[j]));
				}
			}
			if(temp.type=='c'||temp.type=='C')  //聊天
			{
				printf("%s发送了一条消息\n",temp.name);
				for(int j=0;j<=maxi;j++)
				{
					if(cintemp.sin_port==cin[j].sin_port)
					{
						continue;
					}
	
					sendto(sfd,&temp,sizeof(temp),0,(struct sockaddr*)&cin[j],sizeof(cin[j]));
				}
			}
			if(temp.type=='q'||temp.type=='Q')  //退出协议
			{
				int i=0;
				if(strcmp(temp.text,"quit")==0)
				{
					strcpy(temp.name,msg[i].name);
				}
				printf("%s[%s:%d]:已离线\n",temp.name,inet_ntoa(cintemp.sin_addr),ntohs(cintemp.sin_port));

				for(i=0;i<=maxi;i++)
				{
					if(cintemp.sin_port==cin[i].sin_port)
					{
						int t=i;

						for(int j=maxi;j>=i;j--)
						{
							cin[t]=cin[t+1];
							msg[t]=msg[t+1];
							t++;
						}
						maxi--;
					}
					sendto(sfd,&temp,sizeof(temp),0,(struct sockaddr*)&cin[i],sizeof(cin[i]));

				}
			}
		}
		if(FD_ISSET(0,&tempfds))
		{
			bzero(buf,sizeof(buf));
			fgets(buf,sizeof(buf),stdin);
			buf[strlen(buf)-1]='\0';

			if(strcmp(buf,"quit")==0)
			{
				close(sfd);
				return 0;
			}

			temp.type='C';
			strcpy(temp.text,buf);
			strcpy(temp.name,"***system***");
			for(int i=0;i<=maxi;i++)
			{
				sendto(sfd,&temp,sizeof(temp),0,(struct sockaddr*)&cin[i],sizeof(cin[i]));
			}
		}

	}
	//5、关闭套接字文件描述符
	close(sfd);
	return 0;
}

客户端

#include <myhd.h>

//传输结构体
struct cli
{
	char type;  //  L/C/Q协议
	char name[20];
	char text[128];
};
int main(int argc, const char *argv[])
{
	if(argc!=3)
	{
		printf("请输入服务器和端口号\n");
		return -1;
	}

	//创建昵称
	char n_name[20]="";
	printf("请输入昵称:");
	scanf("%s",n_name);
	getchar();

	//1、创建客户端套接字文件描述符
	int cfd=socket(AF_INET,SOCK_DGRAM,0);
	if(cfd<0)
	{
		perror("socket error");
		return -1;
	}
	printf("socket success cfd=%d\n",cfd);
	//填充服务器端信息结构体
	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]);
	socklen_t socklen=sizeof(sin);
	char buf[128]="";
	char rbuf[128]="";

	int res=0; //检测select

	//定义用于检测文件描述符的集合
	fd_set readfds,tempfds;
	//清空容器中的内容
	FD_ZERO(&readfds);
	//将要检测的文件描述符放入集合中
	FD_SET(cfd,&readfds);
	FD_SET(0,&readfds);


	//创建客户端的同时,向服务器发送一个L协议的结构体
	struct cli cmsg;
	cmsg.type='L';
	strcpy(cmsg.name,n_name);
	sendto(cfd,&cmsg,sizeof(cmsg),0,(struct sockaddr*)&sin,sizeof(sin));

	//2、收发数据
	while(1)
	{
		//复制一份
		tempfds=readfds;
		//使用select阻塞等待集合中的文件描述符
		res=select(cfd+1,&tempfds,NULL,NULL,NULL);
		if(res==-1)
		{
			perror("select error");
			return -1;
		}
		else if(res==0)
		{
			printf("time out\n");
			return -1;
		}
		
			if(FD_ISSET(0,&tempfds))
			{
				
				bzero(buf,sizeof(buf));
				fgets(buf,sizeof(buf),stdin);
				buf[strlen(buf)-1]='\0';
				if(strcmp(buf,"quit")==0)
				{
					cmsg.type='Q';
					strcpy(cmsg.name,n_name);
					sendto(cfd,&cmsg,sizeof(cmsg),0,(struct sockaddr*)&sin,sizeof(sin));
					close(cfd);
					return 0;
				}
				else
				{
					strcpy(cmsg.name,n_name);
					strcpy(cmsg.text,buf);
					cmsg.type='C';
					sendto(cfd,&cmsg,sizeof(cmsg),0,(struct sockaddr*)&sin,sizeof(sin));
				}

			}
			if(FD_ISSET(cfd,&tempfds))
			{
				bzero(buf,sizeof(buf));
				bzero(rbuf,sizeof(rbuf));

				recvfrom(cfd,&cmsg,sizeof(cmsg),0,NULL,NULL);
				if(cmsg.type=='L')
				{
					printf("-----%s登陆成功-----\n",cmsg.name);
				}
				if(cmsg.type=='Q')
				{
					printf("-----%s已离线-----\n",cmsg.name);
				}
				if(cmsg.type=='C')
				{
					strcpy(buf,cmsg.text);
					strcpy(rbuf,cmsg.name);
					printf("%s:%s\n",rbuf,buf);
					if(strcmp(cmsg.name,"***system***"))
					{
						strcpy(cmsg.name,n_name);
					}
				}
			}
	}
	//4、关闭套接字文件描述符
	close(cfd);
	return 0;
}

结果演示

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

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

相关文章

Kubernetes Dashboard 涉及的一些常规技巧

Kubernetes Dashboard 提供了一个GUI形式的K8S集群管理工具&#xff0c;通过它我们能很容易的观察到集群资源消耗情况、服务器运行状态以及针对Pod的相关观察与操作&#xff1b; Dashboard 的相关配置 Dashboard 提供了通过配置启动命令行参数来控制其相关行为的能力&#xf…

Docker—共享应用程序

现在您已经构建了一个映像&#xff0c;可以共享它。要共享Docker映像&#xff0c;您必须使用Docker注册表。默认注册表是Docker Hub&#xff0c;是您使用的所有图像的来源。 Docker ID&#xff08;Docker标识&#xff09; Docker ID允许您访问Docker Hub&#xff0c;这是世界上…

Hive安装与配置

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

Linux系统---环境变量+内核进程调度队列(选学)

顾得泉&#xff1a;个人主页 个人专栏&#xff1a;《Linux操作系统》 《C/C》 键盘敲烂&#xff0c;年薪百万&#xff01; 一、环境变量 1.基本概念 环境变量(environment variables)一般是指在操作系统中用来指定操作系统运行环境的一些参数&#xff0c;如: 我们在编写CI/…

卓越进行时 | 西安交通大学校友莅临赛宁网安参观考察

近日&#xff0c;为了深入贯彻网络安全强国战略建设&#xff0c;积极发挥网络安全企业的先进作用&#xff0c;推动校企合作与协作共赢。西安交通大学领导携校友会来到赛宁网安网络安全卓越中心进行参观考察&#xff0c;为进一步的校企合作和产业孵化奠定基础。 活动期间&#…

Maven——Maven使用基础

1、安装目录分析 1.1、环境变量MAVEN_HOME 环境变量指向Maven的安装目录&#xff0c;如下图所示&#xff1a; 下面看一下该目录的结构和内容&#xff1a; bin&#xff1a;该目录包含了mvn运行的脚本&#xff0c;这些脚本用来配置Java命令&#xff0c;准备好classpath和相关…

C语言数据结构之顺序表(上)

前言&#xff1a; ⭐️此篇博文主要分享博主在学习C语言的数据结构之顺序表的知识点时写的笔记&#xff0c;若有错误&#xff0c;还请佬指出&#xff0c;一定感谢&#xff01;制作不易&#xff0c;若觉得内容不错可以点赞&#x1f44d;收藏❤️&#xff0c;这是对博主最大的认可…

C++基础 -10- 类

类的格式 public:公共成员 类外可访问 protected:保护成员 类外不可访问 private:私有成员 类外不可访问 class base {public:int a;protected:int b;private:int c;};

学生护眼灯怎么选?2023备考护眼台灯推荐

近期&#xff0c;许多“护眼台灯是否是智商税”的帖子频繁出现&#xff0c;引起了许多群众的关注&#xff0c;作为一名护眼台灯资深使用者&#xff0c;在这里声明一下&#xff0c;护眼台灯绝对不是智商税。护眼台灯是通过调节光线亮度和色温&#xff0c;降低蓝光辐射&#xff0…

ubuntu22.04新机使用(换源,下载软件,安装显卡驱动,锁屏长亮)

换源 国内有很多Ubuntu的镜像源&#xff0c;包括阿里的、网易的&#xff0c;还有很多教育网的源&#xff0c;比如&#xff1a;清华源、中科大源。推荐使用中科大源&#xff0c;快得很。 /etc/apt/sources.list编辑/etc/apt/sources.list文件, 在文件最前面添加以下条目(操作前…

《微信小程序开发从入门到实战》学习三十六

4.2 云开发JSON数据库 4.2.6 云开发JSON数据库 在集合对象上调用add方法可以在集和中可以插入一条记录&#xff0c;代码如下&#xff1a; db.collection(testOne).add({ // 在JSON数据库的testOne集合中增加一个记录 data:{ name: "write paper" }, // 插入数据成功…

js实现鼠标拖拽

目录 css代码 html代码 js代码 完整代码 效果图&#xff1a; 需求&#xff1a; 鼠标在图片内按下时 图片可以跟随盒子动 鼠标弹起图片停下来 如果图片在box的盒子里面时鼠标弹起了 就把图片展示在box里面 并且让图片回到起始位置 css代码 .div {width: 100px;height: 10…

SpringBoot+VUE3前后端分离-【支付宝支付】

1、支付宝沙箱应用申请 https://open.alipay.com/develop/sandbox/app 打开支付宝沙箱能够看到如下信息&#xff1a; 获取到appid&#xff1b; 2、获取应用私钥以及支付宝公钥 在接口加密方式选择公钥模式启用&#xff0c;根据操作即可获取应用公钥、应用私钥以及支付宝公钥…

Rust UI开发(四):iced中如何添加菜单栏(串口调试助手)

注&#xff1a;此文适合于对rust有一些了解的朋友 iced是一个跨平台的GUI库&#xff0c;用于为rust语言程序构建UI界面。 这是一个系列博文&#xff0c;本文是第四篇&#xff0c;前三篇链接&#xff1a; 1、Rust UI开发&#xff08;一&#xff09;&#xff1a;使用iced构建UI时…

PyTorch入门教学——加载数据(Dataset)

1、简介 PyTorch中如何读取数据主要涉及到两个类&#xff0c;分别为Dataset和Dataloader。 Dataset&#xff1a;创建可被Pytorch使用的数据集Dataloader&#xff1a;向模型传递数据本文主要讲解Dataset的使用方法。 2、Dataset 2.1、查看使用方法 打开Anaconda Prompt&…

双十二有什么好物是值得推荐?智能家居好物推荐

都知十一月份跟十二月份都有两个大促的时间&#xff0c;那就是双十一跟双十二&#xff0c;距离双十一过去已经半个月了&#xff0c;是不是还有很多朋友在双十一的时候也没有买尽兴&#xff0c;别慌&#xff01;错过了双十一咱还有双十二&#xff0c;双十二的优惠力度也不会低于…

mysql 性能排查

mysql 下常见遇到的问题有&#xff0c;mysql连接池耗尽&#xff0c;死锁、慢查、未提交的事务。等等我们可能需要看&#xff1b;我们想要查看的可能有 1.当前连接池连接了哪些客户端&#xff0c;进行了哪些操作 2.当前造成死锁的语句有哪些&#xff0c;是哪个客户端上的&#x…

链接共享平台LinkStack

什么是 LinkStack &#xff1f; LinkStack 是一个独特的平台&#xff0c;为在线管理和共享链接提供了高效的解决方案。平台提供了一个类似于 Linktree 的网站&#xff0c;它可以让用户克服社交媒体平台上只能添加一个链接的限制。借助 LinkStack&#xff0c;用户可以轻松链接到…

Labview Lite Note

目录 001十六进制字符串转浮点数002浮点数转十六进制字符串 001十六进制字符串转浮点数 002浮点数转十六进制字符串

使用elasticsearch-head插件修改elasticsearch数据

1、先使用elasticsearch-head插件基本查询功能找到要修改的数据&#xff0c;看看是否存在 2、切换到elasticsearch-head复合查询界面&#xff0c;输入数据修改地址&#xff1a; http://es的ip地址:端口号/索引名称/文档类型&#xff08;没特殊设置过就是_doc&#xff09;/文档…