基于UDP实现的网络聊天室

这篇具有很好参考价值的文章主要介绍了基于UDP实现的网络聊天室。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。

服务器:

#include <myhead.h>
struct msg
{
	char type;
	char name[20];
	char text[1024];
};

int main(int argc, const char *argv[])
{
	if(argc!=3)
	{
		printf("input error\n");
		printf("./a.out IP地址 端口号\n");
		return -1;
	}

    //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;                                                                     
        }  

    //2、绑定IP地址和端口号
    //2.1填充地址信息结构体
    struct sockaddr_in sin;
    sin.sin_family = AF_INET;          //地址族
	short port=(short)atoi(argv[2]);
    sin.sin_port = htons(port);        //端口号
    sin.sin_addr.s_addr = inet_addr(argv[1]);   //IP地址


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

	 //定义容器接收对端地址信息结构体
    struct sockaddr_in cin;
    socklen_t socklen = sizeof(cin);

	//定义存储客户端地址信息结构体信息
	struct sockaddr_in scin[1024];
	for(int i=0;i<1024;i++)
	{
		scin[i].sin_family=AF_INET;
	}

	 //1、创建文件描述符容器
    fd_set readfds, tempfds;
    //2、清空容器内容
    FD_ZERO(&readfds);
    //3、将sfd和0号文件描述符放入容器中
    FD_SET(0, &readfds);
    FD_SET(sfd, &readfds);

	//定义结构体变量,用于接收和发送,和客户端进行通信
	struct msg send;
	struct msg in;
	
	int res;
	char buf[128]="";
	char address[128]="";
	int n=0;

	while(1)
	{
		bzero(buf,sizeof(buf));
		bzero(address,sizeof(address));
		tempfds = readfds;      //将要检测的容器复制保存一份
	    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))
		{
			res=recvfrom(sfd,&in,sizeof(in),0,(struct sockaddr*)&cin,&socklen);
			if(res==-1)
			{
				perror("recvfrom error");
				return -1;
			}
			if(in.type=='L')
			{
				scin[n]=cin;
				n++;
			//	sprintf(buf,"---%s 已上线---",in.name);
				sprintf(address,"---%s[%s:%d]登录成功---",in.name,inet_ntoa(cin.sin_addr),ntohs(cin.sin_port));
				printf("%s\n",address);
				for(int i=0;i<n;i++)
				{
					if(scin[i].sin_port==cin.sin_port)
					{
						continue;
					}
					sendto(sfd,&in,sizeof(in),0,(struct sockaddr*)&scin[i],sizeof(scin[i]));
				}
				bzero(address,sizeof(address));
			}
			if(in.type=='C')
			{
				sprintf(address,"---%s[%s:%d]chat成功---",in.name,inet_ntoa(cin.sin_addr),ntohs(cin.sin_port));
				printf("%s\n",address);

				//群聊
				send.type=in.type;
				strcpy(send.name,in.name);
				strcpy(send.text,in.text);
				for(int i=0;i<n;i++)
				{
					if(scin[i].sin_port==cin.sin_port)
					{
						continue;
					}
					sendto(sfd,&send,sizeof(send),0,(struct sockaddr*)&scin[i],sizeof(scin[i]));


				}
			}
			if(in.type=='Q')
			{
				//下线
				send.type=in.type;
				strcpy(send.name,in.name);
				strcpy(send.text,in.text);

				for(int i=0;i<n;i++)
				{
					bzero(buf,sizeof(buf));
					sprintf(buf,"---%s已下线---\n",send.name);
					printf("%s\n",buf);
					//删除用户
					if(scin[i].sin_port==cin.sin_port)
					{
						int t=i;
						for(int j=i;j<=n;j++)
						{
							scin[t]=scin[t+1];
							t++;
						}
					}
					n--;
					sendto(sfd,&send,sizeof(send),0,(struct sockaddr*)&scin[i],sizeof(scin[i]));
				}
			
			}
		}
		if(FD_ISSET(0,&tempfds))
		{
			//用于接收系统的消息
			bzero(&send,sizeof(send));
			strcpy(send.name,"系统消息");
			fgets(send.text,sizeof(send.text),stdin);
			send.text[strlen(send.text)-1]=0;
			send.type='C';
			for(int i=0;i<=n;i++)
			{
				sendto(sfd,&send,sizeof(send),0,(struct sockaddr*)&scin[i],sizeof(scin[i]));
			}
		}


	}

	close(sfd);



	return 0;
}

客户端:

#include <myhead.h>
struct msg
{
	char type;
	char name[20];
	char text[1024];
};

int main(int argc, const char *argv[])
{
	if(argc!=3)
	{
		printf("input error\n");
		printf("usage:./a.out IP地址 端口号\n");
		return -1;
	}

	//1、创建用于通信的套接字
    int sfd = socket(AF_INET, SOCK_DGRAM, 0);
    if(sfd == -1)
    {
        perror("socket error");
        return -1;
    }

	//2、绑定IP地址和端口号
    //2.1填充服务器端地址信息结构体
    struct sockaddr_in sin;
	short port=(short)atoi(argv[2]);
    sin.sin_family = AF_INET;          //地址族
    sin.sin_port = htons(port);        //端口号
    sin.sin_addr.s_addr = inet_addr(argv[1]);   //IP地址
	
	//定义容器接收服务器端地址信息结构体
    socklen_t socklen = sizeof(sin);



	//定义结构体变量,用于发送和接收
	struct msg send;
	struct msg in;
	printf("请输入用户名>>>");
	fgets(send.name,sizeof(send.name),stdin);
	send.name[strlen(send.name)-1]=0;
	send.type='L';
	//将登录的用户名发送给服务器
	sendto(sfd,&send,sizeof(send),0,(struct sockaddr*)&sin,socklen);
	
    //1、创建文件描述符容器
    fd_set readfds, tempfds;
    //2、清空容器内容
    FD_ZERO(&readfds);
    //3、将sfd和0号文件描述符放入容器中
    FD_SET(0, &readfds);
    FD_SET(sfd, &readfds);

	int res1;
	char buf[128]="";

	while(1)
	{
		 tempfds = readfds;      //将要检测的容器复制保存一份
        int 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))
		{
			res1=recvfrom(sfd,&in,sizeof(in),0,(struct sockaddr*)&sin,&socklen);
			if(res1==-1)
			{
				perror("recvfrom error");
				return -1;
			}
			if(in.type=='L')
			{
				printf("---%s上线了---\n",in.name);
			}
			if(in.type=='C')
			{
				printf("%s: %s\n",in.name,in.text);
			}
			if(in.type=='Q')
			{
				printf("---%s已下线---\n",in.name);
			}

		}
		//如果程序执行到此,说明检测的集合中有事件产生
        if(FD_ISSET(0, &tempfds))       //表示sfd触发了事件
		{
			//判断是群聊还是退出
			bzero(send.text,sizeof(send.text));
			fgets(send.text,sizeof(send.text),stdin);
			send.text[strlen(send.text)-1]=0;
			if(strcmp(send.text,"quit")==0)
			{
				send.type='Q';
				sendto(sfd,&send,sizeof(send),0,(struct sockaddr*)&sin,socklen);
				break;
			}else
			{
				send.type='C';
				sendto(sfd,&send,sizeof(send),0,(struct sockaddr*)&sin,socklen);
			}
		}

	}
	close(sfd);
	return 0;
}

运行结果:

基于UDP实现的网络聊天室,网络,udp,网络协议文章来源地址https://www.toymoban.com/news/detail-837258.html

到了这里,关于基于UDP实现的网络聊天室的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包 赞助服务器费用

相关文章

  • 网络聊天室的UDP实现以及数据库

    网络聊天室UDP实现 服务器端: 头文件: 主函数: 自定义函数: 客户端: 思维导图:

    2024年03月21日
    浏览(34)
  • 【网络编程】UDP简单实现翻译软件与网络聊天室

    在上一章【网络编程】demo版UDP网络服务器实现实现了客户端和服务端之间的数据的发送与接收,上一章我们是直接让服务端把接收到的数据打印出来。 但是服务端并不是只接收到数据就完了,它还要 处理任务 。 所以我们可以在服务端设置一个回调函数: 用来处理接收到的

    2024年02月05日
    浏览(60)
  • C语言实现--基于UDP的多人在线聊天室

    目录 实现功能 实现思想 实现代码(部分及详解) 服务端部分代码 客户端部分代码 实现效果 项目中出现的问题和解决方法 项目整体代码展示 代码优化思路 服务端代码 客户端代码 服务端可以同时连接多个客户端; 新的客户端连接服务端时,可以在服务端显示自己的名字并

    2024年02月04日
    浏览(46)
  • 【网络编程】利用套接字实现一个简单的网络通信(UDP实现聊天室 附上源码)

    源IP地址(Source IP Address): 源IP地址是数据包发送方(或数据流出发点)的唯一标识符。它用于在互联网或本地网络中定位发送数据包的设备或主机。源IP地址是数据包的出发点,即数据从这个地址开始传送,向目的IP地址指示的设备发送。 在TCP/IP协议中,源IP地址通常由发

    2024年02月14日
    浏览(67)
  • Linux 基本语句_16_Udp网络聊天室

    服务端代码: 客户端代码: 总体效果是客户上线状态、退出状态、发送的消息都能通过广播,将信息发送给所有在线客户端,服务端能接收并显示所有客户端发送的消息,且也具备广播能力 服务端: 服务端创建了一个链表,这个链表中的每个节点是专用于储存客户端的ip地

    2024年02月04日
    浏览(27)
  • 计算机网络 TCP/UDP程序开发网络聊天室

    TCP/UDP程序开发 开发TCP/UDP协议应用程序,掌握网络应用程序的工作原理。通过该实验,深入理解UDP和TCP协议的异同点,了解网络协议的工作过程,学会网络通信编程的基本方法,能够编制网络应用程序。 (1)了解和掌握“基于UDP-面向无连接的应用程序/基于TCP-面向连接的

    2024年02月05日
    浏览(59)
  • 【嵌入式学习】网络通信基础-项目篇:简单UDP聊天室

    源码已在GitHub开源:0clock/LearnEmbed-projects/chat 客户端功能: 上线发送登录的用户名[yes] 发送消息和接收消息[yes] quit退出 服务器端功能: 统计用户上线信息,放入链表中[yes] 接收用户信息并给其他用户发送消息[yes] 服务器也支持给所有用户群发消息[yes] 接收下线提醒

    2024年01月25日
    浏览(39)
  • UDP聊天室

    1.头文件 2.服务器 3.客户端 4.makefile 5.结果

    2024年02月10日
    浏览(24)
  • UDP套接字的通信(实现英汉互译/程序替换/多线程聊天室/Windows与Linux通信)

    我们在客户端发英文,服务端做翻译工作,让翻译好的中文再次发给我们的客户端,然后打印出来。 翻译的操作 创建一个txt文件里面包含英汉互译的数据 dict.txt 对txt中的数据进行操作 分割函数 将英汉通过冒号分开。 将文件数据插入map里面 重新加载文件 通过捕捉2号(ctrl

    2024年02月11日
    浏览(23)
  • 基于TCP协议的聊天室详细教学(C++)

    服务器只转发消息不参到信息交流中 客户端输入用户名后默认进入群聊模式,输入“获取用户列表”可以获取在线用户用户名列表,如果需要私聊某一个用户需要输入“私聊+用户名”可进入私聊模式,输入“退出私聊”可退出私聊重新进入群聊模式。 基本群聊展示 获取用户

    2024年02月08日
    浏览(45)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包