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

客戶端:子進程發送信息父進程接受信息node

服務器:子進程發送廣播信息,父進程接受信息服務器

client.csocket

#include<stdio.h>
#include<stdlib.h>
#include<string.h>
#include<errno.h>
#include<sys/types.h>
#include<sys/socket.h>
#include<netinet/in.h>
#include<arpa/inet.h>
#include<unistd.h>
#include<signal.h>

#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<stdio.h>
#include<stdlib.h>
#include<string.h>
#include<errno.h>
#include<sys/types.h>
#include<sys/socket.h>
#include<netinet/in.h>
#include<arpa/inet.h>
#include<unistd.h>
#include<signal.h>

#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 第二個是端口ui

程序流程圖及主要結構體spa

typedef struct msgcode

{server

    char type;      //消息類型進程

    char name[N];  //客戶名稱ip

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

}MSG;

typedef struct node    //存放客戶端的IP的鏈表

{

    struct sockaddr_in  addr;

    struct node *next;

}listnode, *linklist;

相關文章
相關標籤/搜索