linux c 基于UDP的多人聊天程序

2019独角兽企业重金招聘Python工程师标准>>> hot3.png

客户端:子进程发送信息父进程接受信息

服务器:子进程发送广播信息,父进程接受信息

client.c

#include
#include
#include
#include
#include
#include
#include
#include
#include
#include

#define N 128

typedef struct
{
	char type;
	char name[32];
	char text[N];
}MSG;

int main(int argc,char *argv[])
{
	int socketfd;
	socklen_t addr_len;
	pid_t pid;
	MSG msg;
	struct sockaddr_in server_addr;
	if(argc < 3)
	{
		printf("uasge: %s ip port\n",argv[0]);
		exit(-1);
	}

	if((socketfd = socket(PF_INET,SOCK_DGRAM,0)) < 0)
	{
		perror("socket");
		exit(-1);
	}
	printf("input name:\n");
	fgets(msg.name,64,stdin);
	msg.name[strlen(msg.name) - 1] = '\0';
	msg.type='L';

	memset(&server_addr,0,sizeof(server_addr));
	server_addr.sin_family = AF_INET;
	server_addr.sin_addr.s_addr = inet_addr(argv[1]);
	server_addr.sin_port = htons(atoi(argv[2]));
	addr_len = sizeof(server_addr);
	
	if(sendto(socketfd,&msg,sizeof(msg),0,(struct sockaddr*)&server_addr,addr_len) < 0)
	{
		perror("sendto3");
		exit(-1);
	}

	if((pid = fork()) == -1 )
	{
		perror("fork");
		exit(-1);
	}
	if(pid == 0)
	{
		while(1)
		{
			fgets(msg.text,N,stdin);
			msg.text[strlen(msg.text) - 1] = '\0';

			if(strncmp(msg.text,"quit",4) == 0)
			{
				msg.type = 'Q';
				if(sendto(socketfd,&msg,sizeof(msg),0,(struct sockaddr*)&server_addr,addr_len) < 0)
				{
					perror("sendto2");
					exit(-1);
				}
				kill(getppid(),SIGKILL);
				break;	
			}
			else
			{
				msg.type='B';
				if(sendto(socketfd,&msg,sizeof(msg),0,(struct sockaddr*)&server_addr,addr_len) < 0)
				{
					perror("sendto1");
					exit(-1);
				}	
			}
		
		}
		close(socketfd);
	}

	if(pid > 0)
	{
		while(1)
		{
			if(recvfrom(socketfd,&msg,sizeof(msg),0,(struct sockaddr*)&server_addr,&addr_len) < 0)
			{
				perror("recvfrom");
				exit(-1);
			}
		
			switch(msg.type)
			{
				case 'L':
					printf("%s login\n",msg.name);
					break;
				case 'B':
					printf("from %s> %s\n",msg.name,msg.text);
					break;
				case 'Q':
					printf("%s quit\n",msg.name);
					break;
			}
		}
	}	
	return 0;
}

server.c
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include

#define N 128
#define L 1
#define B 2
#define Q 3

typedef struct 
{
	char type;
	char name[32];
	char text[N];
}MSG;

typedef struct node
{
	struct sockaddr_in addr;
	struct node *next;
}listnode,*linklist;

linklist linklist_create()
{
	linklist H;
	H = (linklist)malloc(sizeof(listnode));
	memset(H,0,sizeof(listnode));
	H->next = NULL;
	return H;
}

void  insert_data(linklist H,struct sockaddr_in client_addr)
{
	linklist p = NULL;
	p =(linklist)malloc(sizeof(listnode));
	p->addr = client_addr;
	p->next = H->next;
	H->next = p;
	return ;
}

void process_login(int socketfd,linklist H,MSG msg,struct sockaddr_in client_addr)
{
	insert_data(H,client_addr);
	linklist h1 = H;
	while(h1->next != NULL)
	{
		h1 = h1->next;

		if(memcmp(&client_addr,&h1->addr,sizeof(client_addr)) != 0 )
		{
			if(sendto(socketfd,&msg,sizeof(msg),0,(struct sockaddr*)&(h1->addr),sizeof(h1->addr)) < 0)
			{
				perror("sendto4");
				exit(-1);
			}
		}
	}
	return ;
}

void process_broadcast(int socketfd,linklist H,MSG msg,struct sockaddr_in client_addr)
{
	linklist h1 = H;
	while(h1->next != NULL)
	{
		h1 = h1->next;
		if(memcmp(&client_addr,&h1->addr,sizeof(client_addr)) != 0)
		{
			if(sendto(socketfd,&msg,sizeof(msg),0,(struct sockaddr*)&(h1->addr),sizeof(h1->addr)) < 0)
			{
				perror("sendto3");
				exit(-1);
			}
		}
	}
	return ;
}

void process_quit(int socketfd,linklist H,MSG msg,struct sockaddr_in client_addr)
{
	linklist p = H;
	linklist q;
	while(p->next)
	{
		if(memcmp(&client_addr,&p->next->addr,sizeof(client_addr)) == 0)
		{
			q = p->next;
			p->next = q->next;
			free(q);
			q = NULL;
		}
		else
		{
			if(sendto(socketfd,&msg,sizeof(msg),0,(struct sockaddr*)&p->next->addr,sizeof(p->next->addr)) < 0)
			{
				perror("sendto");
				exit(-1);
			}
			p = p->next;
		}
	}
	return ;
}

int main(int argc,char *argv[])
{
	int socketfd;
	socklen_t addr_len;
	pid_t pid;
	MSG msg;
	struct sockaddr_in server_addr,client_addr;
	if(argc < 3)
	{
		printf("uasge: %s ip port\n",argv[0]);
		exit(-1);
	}

	memset(&server_addr,0,sizeof(server_addr));
	server_addr.sin_family = AF_INET;
	server_addr.sin_addr.s_addr = inet_addr(argv[1]);
	server_addr.sin_port = htons(atoi(argv[2]));
	if((socketfd = socket(PF_INET,SOCK_DGRAM,0)) < 0)
	{
		perror("socket");
		exit(-1);
	}

	if(bind(socketfd,(struct sockaddr*)&server_addr,sizeof(server_addr)) < 0)
	{
		perror("bind");
		exit(-1);
	}
	addr_len = sizeof(client_addr);
	linklist H = linklist_create();

	if((pid = fork()) == -1)
	{
		perror("fork");
		exit(-1);
	}
	if(pid == 0)
	{
		while(1)
		{
			fgets(msg.text,N,stdin);
			msg.text[strlen(msg.text)-1] = '\0';
			strcpy(msg.name,"server");
			msg.type = 'B';
			if(sendto(socketfd,&msg,sizeof(msg),0,(struct sockaddr*)&server_addr,sizeof(server_addr)) < 0)
			{
				perror("sendto1");
				close(socketfd);
				exit(-1);
			}

		}
	}
	else if(pid > 0)
	{
		while(1)
		{
			if(recvfrom(socketfd,&msg,sizeof(msg),0,(struct sockaddr*)&client_addr,&addr_len) < 0)
			{
				perror("recvfrom");
				close(socketfd);
				exit(-1);
			}
		
			switch(msg.type)
			{
				case 'L':
					process_login(socketfd,H,msg,client_addr);
					break;
				case 'B':
					process_broadcast(socketfd,H,msg,client_addr);
					break;
				case 'Q':
					process_quit(socketfd,H,msg,client_addr);
					break;
			}
		}
	}

	return 0;
}

运行时须带两个参数 第一个是ip 第二个是端口

程序流程图及主要结构体

typedef struct msg

{

    char type;      //消息类型

    char name[N];  //客户名称

    char text[N];  //消息正文

}MSG;

typedef struct node    //存放客户端的IP的链表

{

    struct sockaddr_in  addr;

    struct node *next;

}listnode, *linklist;

linux c 基于UDP的多人聊天程序_第1张图片

 

 

转载于:https://my.oschina.net/u/130360/blog/71015

你可能感兴趣的:(linux c 基于UDP的多人聊天程序)