UDP网络聊天室(更)

服务器端

cs 复制代码
#include <header.h>
typedef struct node
{
	char name[20];
	struct sockaddr_in cli_addr;
	struct node *next;
}node,*node_p;
typedef struct msg
{
	char type;
	char name[20];
	char text[128];
}msg;
node_p create_link()
{
	node_p H=(node_p)malloc(sizeof(node));
	if(H==NULL)
	{
		printf("apply fail\n");
		return NULL;
	}
	H->next=NULL;
	return H;
}
node_p create_node(char *name,struct sockaddr_in cli_addr)
{
	node_p new=(node_p)malloc(sizeof(node));
	if(new==NULL)
	{
		printf("apply fail\n");
		return NULL;
	}
	strcpy(new->name,name);
	new->cli_addr=cli_addr;
	new->next=NULL;
	return new;
}
void insert(node_p H,char *name,struct sockaddr_in cli_addr)
{
	if(H==NULL)
	{
		printf("apply fail\n");
		return;
	}
	node_p new=create_node(name,cli_addr);
	new->next=H->next;
	H->next=new;
}
void delete(node_p H,char* name)
{
	if(H==NULL)
	{
		printf("apply fail\n");
		return;
	}
	node_p p=H->next;
	while(p!=NULL&&strcmp(p->next->name,name)!=0)
	{
		p=p->next;
	}
	node_p p1=p->next;
	p->next=p->next->next;
	free(p1);
}
int main(int argc, const char *argv[])
{
	if(argc!=3)
	{
		printf("请依次输入正确的ip地址和端口号!\n");
		return 1;
	}
	const char *SER_IP=argv[1];
	int SER_PORT=atoi(argv[2]);

	int sfd=socket(AF_INET,SOCK_DGRAM,0);               
	if(sfd==-1)
	{
		perror("socket");
		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");
		return 1;
	}
	struct sockaddr_in cin;
	socklen_t addrlen=sizeof(cin);
	char wbuf[128]={0};
	struct pollfd pfd[2];
	pfd[0].fd=sfd;
	pfd[1].fd=0;
	pfd[0].events=POLLIN;
	pfd[1].events=POLLIN;
	node_p H=create_link();
	msg msg;
	printf("等待用户加入....\n");
	while(1)
	{
		int res=poll(pfd,2,-1);
		if(res==-1)
		{
			perror("poll");
			return 1;
		}
		else if(res==0)
		{
			printf("time out\n");
			return 1;
		}
		if(pfd[0].revents==POLLIN)
		{
			memset(&msg,0,sizeof(msg));
			recvfrom(sfd,&msg,sizeof(msg),0,(struct sockaddr*)&cin,&addrlen);
			if(msg.type=='n')
			{
				node_p p=H->next;
				insert(H,msg.name,cin);
				printf("*********\033[1;35m[%s\033[0m:\033[1;32m%d] \033[33m %s\033[0m\033[1;36m 已进入聊天室\033[0m*********** \n",inet_ntoa(cin.sin_addr),ntohs(cin.sin_port),msg.name);
				while(p!=NULL)
				{
					sendto(sfd,&msg,sizeof(msg),0,(struct sockaddr*)&p->cli_addr,sizeof(p->cli_addr));
					p=p->next;
				}
			}
			else if(msg.type=='t')
			{
				node_p p=H->next;
				printf("%s:%s\n",msg.name,msg.text);
				while(p!=NULL)
				{
					msg.type='t';
					if(strcmp(p->name,msg.name)!=0)
					{
						sendto(sfd,&msg,sizeof(msg),0,(struct sockaddr*)&p->cli_addr,sizeof(p->cli_addr));
					}
					p=p->next;
				}
			}
			else if(msg.type=='q')
			{
				printf("\033[1;36m%s离开了聊天室...\n",msg.name);
				node_p p=H->next;
				while(p!=NULL)
				{
					msg.type='q';
					sendto(sfd,&msg,sizeof(msg),0,(struct sockaddr*)&p->cli_addr,sizeof(p->cli_addr));
					p=p->next;
				}
			}
		}
		if(pfd[1].revents==POLLIN)
		{
			msg.type='s';
			bzero(wbuf,sizeof(wbuf));
			fgets(wbuf,sizeof(wbuf),stdin);
			strcpy(msg.text,wbuf);
			msg.text[strlen(msg.text)-1]=0;
			node_p p=H->next;
			while(p!=NULL)
			{
				msg.type='s';
				sendto(sfd,&msg,sizeof(msg),0,(struct sockaddr*)&p->cli_addr,sizeof(p->cli_addr));
				p=p->next;
			}
			printf("\033[1;36m系统消息推送成功。\n");
		}
	}
	close(sfd);
	return 0;
}

客户端

cs 复制代码
#include <header.h>
int quit_flag=0;
typedef struct msg
{
	char type;
	char name[20];
	char text[128];
}msg;
int main(int argc, const char *argv[])
{
	if(argc!=3)
	{
		printf("\033[1;35m请依次输入正确的ip地址和端口号!\n");
		return 1;
	}
	const char *SER_IP=argv[1];
	int SER_PORT=atoi(argv[2]);
	printf("\033[1;36m请输入用户名:");
	int cfd=socket(AF_INET,SOCK_DGRAM,0);
	if(cfd==-1)
	{
		perror("socket");
		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 addrlen=sizeof(sin);
	struct pollfd pfd[2];   
	pfd[0].fd=0;
	pfd[1].fd=cfd;
	pfd[0].events=POLLIN;
	pfd[1].events=POLLIN;
	msg msg;
	char username[20]={0};
	fgets(username,sizeof(username),stdin);
	strcpy(msg.name,username);
	msg.name[strlen(msg.name)-1]=0;
	msg.type='n';
	sendto(cfd,&msg,sizeof(msg),0,(struct sockaddr*)&sin,sizeof(sin));
	char rbuf[128]={0};
	while(1)
	{
		int res=poll(pfd,2,-1);
		if(res==-1)
		{
			perror("poll");
			return 1;
		}
		else if(res==0)
		{
			printf("time out\n");
			return 1;
		}
		if(pfd[0].revents==POLLIN)
		{
			msg.type='t';
			strcpy(msg.name,username);
			msg.name[strlen(msg.name)-1]=0;
			char txt[128]={0};
			bzero(txt,sizeof(txt));
			fgets(txt,sizeof(txt),stdin);
			strcpy(msg.text,txt);
			msg.text[strlen(msg.text)-1]=0;
			int flag=0;
			if(strcmp(msg.text,"quit")==0)
			{
				msg.type='q';
				sendto(cfd,&msg,sizeof(msg),0,(struct sockaddr*)&sin,sizeof(sin));
				flag=1;
				quit_flag=1;
			}
			if(flag==0)
			{
				sendto(cfd,&msg,sizeof(msg),MSG_DONTWAIT,(struct sockaddr*)&sin,sizeof(sin));
			}
		}
		if(pfd[1].revents==POLLIN)
		{
			recvfrom(cfd,&msg,sizeof(msg),0,(struct sockaddr*)&sin,&addrlen);
			if(msg.type=='t')
			{
				printf("\033[1;34m%s:\033[0m%s\n",msg.name,msg.text);
			}
			else if(msg.type=='n')
			{
				printf("-----------------\033[1;33m %s \033[1;35m 已上线 \033[1;33m--------------\n",msg.name);
			}
			else if(msg.type=='s')
			{
				printf("\033[1;36msystem:%s\n",msg.text);
			}
			else if(msg.type=='q')
			{
				printf("-----------------\033[1;33m %s\033[1;35m  已下线 \033[1;33m-------------\n",msg.name);
				if(quit_flag==1)
				{
					break;
				}
			}
		}
	}
	close(cfd);
	exit(0);
	return 0;
}

功能实现

相关推荐
莫回首�4 小时前
ubuntu 20.04 多网卡配置,遇到问题总结
linux·网络·ubuntu
星辰徐哥7 小时前
5G的行业应用:工业互联网、车联网、智慧医疗中的网络支撑
网络·5g·php
头疼的程序员8 小时前
计算机网络:自顶向下方法(第七版)第八章 学习分享(三)
网络·学习·计算机网络
@insist1238 小时前
网络工程师-核心考点:网络管理体系与 SNMP 协议全解析
网络·智能路由器·网络工程师·软考·软件水平考试
我科绝伦(Huanhuan Zhou)9 小时前
分享一个网络智能运维系统
运维·网络
codeejun9 小时前
每日一Go-44、Go网络栈深度拆解--从 TCP 到 HTTP 的资源复用艺术
网络·tcp/ip·golang
ayt0079 小时前
Netty AbstractNioChannel源码深度剖析:NIO Channel的抽象实现
java·数据库·网络协议·安全·nio
北京耐用通信9 小时前
无缝衔接·高效传输——耐达讯自动化CC-Link IE转Modbus TCP核心解决方案
网络·人工智能·物联网·网络协议·自动化·信息与通信
亚空间仓鼠10 小时前
OpenEuler系统常用服务(五)
linux·运维·服务器·网络