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

功能实现

相关推荐
QYR_116 小时前
憎水涂料市场分析:2032年全球规模将达46.49亿美元
网络·安全
砚凝霜6 小时前
信息安全工程师下午案例大题冲刺攻略|题型 + 十大专题 + 答题模板 + 数字口诀,直接背
网络
honsor6 小时前
POE供电RJ45以太网温湿度传感器原理、组网与对接实战
网络·物联网·tcp/ip
脆性薄片搬运谢工6 小时前
横架机械手安全光栅保护区域划分的五个核心维度
网络·安全·机器人·脆性薄片搬运专机·伯努利吸盘·超薄玻璃搬运·非接触式上料
workflower7 小时前
无人机注册量与飞行量
大数据·网络·人工智能·云计算·汽车·无人机
上海云盾-小余7 小时前
TCP 洪水与 UDP 反射 DDoS 原理对比:流量放大机制与检测逻辑详解
tcp/ip·udp·ddos
syagain_zsx7 小时前
WebSocket 教程:websocketpp 写 echo 服务端
linux·网络·c++·websocket·网络协议·工具库
骑着蜗牛撵大象3277 小时前
字节序、TLV 到 netlink:Linux 网络消息的编解码全链路
linux·网络·php·etl·序列化·字节序·tlv
漫步人生走在路上8 小时前
外贸SEO中的品牌词与产品词策略:大卖家和小卖家的不同打法
大数据·javascript·网络·数据库·人工智能·搜索引擎
华允物联-HUAIOT8 小时前
DTU 和 LoRa 模块有什么区别?工业无线回传怎么选
网络·tcp/ip·udp