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

功能实现

相关推荐
小马爱打代码2 小时前
Spring Boot 接口安全设计:接口限流、防重放攻击、签名验证
网络·spring boot·安全
giaoho2 小时前
Android网络请求,Retrofit,OKHttp学习
网络
丨千纸鹤丨4 小时前
高可用集群Keepalived
linux·服务器·网络
北极光SD-WAN组网5 小时前
工业互联网时代,如何通过混合SD-WAN提升煤炭行业智能化网络安全
网络·安全·web安全
charlie1145141916 小时前
快速入门Socket编程——封装一套便捷的Socket编程——导论
linux·网络·笔记·面试·网络编程·socket
东风西巷6 小时前
X-plore File Manager v4.34.02 修改版:安卓设备上的全能文件管理器
android·网络·软件需求
liulilittle7 小时前
C++ Proactor 与 Reactor 网络编程模式
开发语言·网络·c++·reactor·proactor
我很好我还能学7 小时前
【计算机网络 篇】TCP基本认识和TCP三次握手相关问题
运维·服务器·网络
苏州向日葵8 小时前
篇五 网络通信硬件之PHY,MAC, RJ45
网络·嵌入式硬件
程序员编程指南8 小时前
Qt 网络编程进阶:WebSocket 通信
c语言·网络·c++·qt·websocket