项目篇:基于UDP通信模型的网络聊天室

发布时间:2024年01月22日

思维导图

基于UDP通信模型的网络聊天室

消息分类及数据包结构

服务器端

#include <head.h>
#define SER_PORT 8888
#define SER_IP "192.168.232.133"
typedef struct mb
{
	struct sockaddr_in cin;
	char name[20];
	struct mb *next;
}*member;
//群发消息
int send_to_all(int sfd,member head,const char *buf,size_t length)
{
	member p=head;
	while(p!=NULL)
	{
		sendto(sfd,buf,length,0,(struct sockaddr*)&(p->cin),sizeof(p->cin));
		p=p->next;
	}
	return 0;
}
//增加成员
member add_member(member head,const char *data,struct sockaddr_in cin)
{
	member p=(member)malloc(sizeof(struct mb));
	p->cin=cin;
	strcpy(p->name,data);
	p->next=head;
	head=p;
	return head;
}
//删除成员
member del_member(member head,const char *name_point)
{
	member p=head;
	if(strcmp(p->name,name_point)==0)
	{
		head=p->next;
		free(p);
		p=NULL;
		return head;
	}
	while(strcmp(p->name,name_point)!=0)
	{
		p=p->next;
	}
	if(p->next==NULL)
	{
		member q=head;
		while(q->next->next!=NULL)
		{
			q=q->next;
		}
		free(p);
		p=NULL;
		q->next=NULL;
		return head;
	}
	member q=head;
	while(strcmp(q->next->name,name_point)!=0)
	{
		q=q->next;
	}
	q->next=p->next;
	free(p);
	p=NULL;
	return head;
}



int main(int argc, const char *argv[])
{

	int sfd=socket(AF_INET,SOCK_DGRAM,0);
	if(sfd==-1)
	{
		perror("socket error:");
		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 error:");
		return -1;
	}
	struct sockaddr_in cin;
	socklen_t socklen=sizeof(cin);
	printf("bind success\n");

	struct pollfd pfd[1024];
	pfd[0].fd=0;
	pfd[0].events=POLLIN;
	pfd[1].fd=sfd;
	pfd[1].events=POLLIN;
	int n=2;
	member head=NULL;

	while(1)
	{
		int res=poll(pfd,n,-1);
		if(res==-1)
		{
			perror("poll error:");
			return -1;
		}
		else if(res==0)
		{
			printf("manbaout\n");
			return -1;
		}
		if(pfd[0].revents==POLLIN)
		{
			//系统发送消息
			char buf[128]="";
			scanf("%s",buf);
			char sys_buf[200];
			sprintf(sys_buf,"***system***>>>%s",buf);
			send_to_all(sfd,head,sys_buf,sizeof(sys_buf));
			printf("系统发送消息\n");
		}
		if(pfd[1].revents==POLLIN)
		{
			//接收消息
			char buf[200]="";
			recvfrom(pfd[1].fd,buf,sizeof(buf),0,(struct sockaddr*)&cin,&socklen);
			short *type_point = (short*)buf;
			switch(ntohs(*type_point))
			{
			case 1:
				{
					//接收到登录的消息
					char *data_point = buf+2;
					char buf[300]="";
					sprintf(buf,"**********%s已登录**********",data_point);
					send_to_all(sfd,head,buf,sizeof(buf));
					head=add_member(head,data_point,cin);
					printf("%s登录\n",data_point);
					break;
				}
			case 2:
				{
					//接收到普通的消息
					char *name_point=buf+2;
					char *data_point=name_point+strlen(name_point)+1;
					char buf[300]="";
					sprintf(buf,"%s>>>%s",name_point,data_point);
					send_to_all(sfd,head,buf,sizeof(buf));
					printf("%s发送消息\n",name_point);
					break;
				}
			case 3:
				{
					//接收到退出消息
					char *name_point=buf+2;
					char *data_point=name_point+strlen(name_point)+1;
					char endbuf[20]="";
					strcpy(endbuf,"quit");
					sendto(sfd,endbuf,sizeof(endbuf),0,(struct sockaddr*)&cin,sizeof(cin));
					del_member(head,name_point);
					char buf[300]="";
					sprintf(buf,"**********%s已下线**********",name_point);
					send_to_all(sfd,head,buf,sizeof(buf));
					printf("%s下线\n",name_point);
					break;
				}
			}
		}
	}
	close(sfd);
	return 0;
}

客户端

#include <head.h>
#define SER_PORT 8888
#define SER_IP "192.168.232.133"

int login(int sfd,struct sockaddr_in sin,const char *name)
{
	
	char buf[200]="";
	short *type_point = (short*)buf;
	char *data_point = buf+2;
	*type_point=htons(1);
	strcpy(data_point,name);

	sendto(sfd,buf,sizeof(buf),0,(struct sockaddr*)&sin,sizeof(sin));
	return 0;
}
int main(int argc, const char *argv[])
{
	int sfd=socket(AF_INET,SOCK_DGRAM,0);
	if(sfd==-1)
	{
		perror("socket error:");
		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 socklen;

	printf("====================欢迎使用网络聊天室====================\n");
	printf("请输入姓名:");
	char name[20];
	scanf("%s",name);

	login(sfd,sin,name);
	
	pid_t pid;
	pid=fork();
	if(pid>0)
	{
		//父进程,用于发消息
		char buf[128]="";
		short *type_point = (short*)buf;
		char *name_point = buf+2;
		strcpy(name_point,name);
		char *data_point=name_point+strlen(name_point)+1;
		while(1)
		{
			scanf("%s",data_point);
			if(strcmp(data_point,"quit")==0)
			{
				*type_point=htons(3);
				sendto(sfd,buf,sizeof(buf),0,(struct sockaddr*)&sin,sizeof(sin));
				break;
			}
			*type_point=htons(2);
			sendto(sfd,buf,sizeof(buf),0,(struct sockaddr*)&sin,sizeof(sin));
		}
	}
	else if(pid==0)
	{
		//子进程,用于接收消息
		while(1)
		{
			char buf[128];
			recvfrom(sfd,buf,sizeof(buf),0,(struct sockaddr*)&sin,&socklen);
			if(strcmp(buf,"quit")==0)
			{
				break;
			}
			printf("%s\n",buf);
		}
	}

	wait(NULL);
	close(sfd);
	return 0;
}

文章来源:https://blog.csdn.net/jackwolfskin2/article/details/135706348
本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。