@expl0r3r
2018-06-26T13:03:45.000000Z
字数 3598
阅读 199
ChatRoom
#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//message structruetypedef struct{char type;char name[32];char text[N];}MSG;//linklist to save socket addressestypedef struct node{struct sockaddr_in addr;struct node *next;}listnode,*linklist;//some variables and structuresint socketfd;socklen_t addr_len;pid_t pid;MSG msg;struct sockaddr_in server_addr,client_addr;//create the head of linklistlinklist linklist_create(){linklist H;H = (linklist)malloc(sizeof(listnode)); //apply room from systemmemset(H,0,sizeof(listnode)); //set value for the room that H pointH -> next = NULL; //set "next" as dangling pointerreturn H;}//insert data into linklistvoid 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 ;}//the process for users to loginvoid 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("sendto failed4");exit(-1);}}}return ;}//the process broadcasting messages to each uservoid 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("sendto failed3");exit(-1);}}}return ;}//the process run if a user quitsvoid 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 failed2");exit(-1);}p = p -> next;}}return ;}//fork function runs once will return two result,the one is 0(means parent process),the other is the ip of the child processvoid start(){linklist H = linklist_create();if ((pid = fork()) == -1){perror("fork failed");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("sendto failed1");close(socketfd);exit(-1);}}}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;}}}}//the initialize function,'argc' means the number of the arrays 'argv','argv[0]' means the path of this file//'argv[1]' and 'argv[2]' mean the two parameters you pass in,the first one is ip,the second one is portvoid init(int argc,char *argv[]){if (argc < 3){printf("usage: %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 failed");exit(-1);}if(bind(socketfd,(struct sockaddr*)&server_addr,sizeof(server_addr)) < 0){perror("bind failed");exit(-1);}addr_len = sizeof(client_addr);}//main functionint main(int argc,char *argv[]){init(argc,argv);start();return 0;}