Linux基础——socket实现简单的群聊程序
首先,我们需要实现数据结构,当有用户连接时,我们将该用户的IP、连接的端口号等保存到一个链表中,
当我们发送消息时,遍历链表,将该消息发送给所有已上线的用户。
当用户下线时,我们将该用户从链表中删除。
服务器实现代码如下:
1 #include <stdio.h> 2 #include <stdlib.h> 3 #include <string.h> 4 #include <sys/socket.h> 5 #include <sys/stat.h> 6 #include <sys/types.h> 7 #include <fcntl.h> 8 #include <netinet/in.h> 9 #include <arpa/inet.h> 10 #include <unistd.h> 11 #include <sys/time.h> 12 #define SIZE 1024 13 typedef struct sockaddr_in SA; 14 typedef struct tag_msg 15 { 16 int msg_type; 17 int msg_len; 18 char msg_buf[SIZE]; 19 }MSG,*pMSG; 20 typedef struct tag 21 { 22 SA addr; 23 struct tag *next; 24 }NODE,*pNODE; 25 void add_list(pNODE *phead,pNODE p) 26 { 27 p->next = *phead; 28 *phead = p; 29 } 30 void del_list(pNODE *phead, SA *p) 31 { 32 pNODE pcur,ppre; 33 pcur = *phead; 34 ppre= NULL; 35 while(pcur) 36 { 37 if(pcur ->addr.sin_port == p->sin_port && pcur->addr.sin_addr.s_addr == p->sin_addr.s_addr) 38 break; 39 else 40 { 41 ppre = pcur; 42 pcur = pcur->next; 43 } 44 } 45 if(ppre == NULL) 46 { 47 *phead=pcur ->next; 48 free(pcur); 49 pcur = NULL; 50 } 51 else 52 { 53 ppre->next = pcur ->next; 54 free(pcur); 55 pcur =NULL; 56 } 57 } 58 void send_msg(int fd,char *msg,pNODE phead) 59 { 60 while(phead) 61 { 62 sendto(fd,msg,strlen(msg),0,(struct sockaddr*)&(phead->addr),sizeof(SA)); 63 phead=phead->next; 64 } 65 } 66 int main(int argc,char *argv[]) 67 { 68 if(argc != 2) 69 { 70 printf("参数不足!!\n"); 71 exit(1); 72 } 73 FILE *fp; 74 pNODE list=NULL; 75 char ip[32]; 76 int port; 77 memset(ip,0,32); 78 fp = fopen(argv[1],"r"); 79 if(fp == NULL) 80 { 81 perror("fopen"); 82 exit(1); 83 } 84 fscanf(fp,"%s%d",ip,&port); 85 fclose(fp); 86 int fd_server; 87 if((fd_server = socket(AF_INET,SOCK_DGRAM,0))==-1) 88 { 89 perror("socket"); 90 exit(1); 91 } 92 SA addr_server; 93 memset(&addr_server,0,sizeof(SA)); 94 addr_server.sin_family = AF_INET; 95 addr_server.sin_port = htons(port); 96 addr_server.sin_addr.s_addr = inet_addr(ip); 97 if(-1 == bind(fd_server,(struct sockaddr *)&addr_server,sizeof(SA))) 98 { 99 perror("bind"); 100 close(fd_server); 101 exit(1); 102 } 103 fd_set read_set,ready; 104 int sel_ret; 105 char buf[1024]; 106 struct timeval tm; 107 MSG my_msg; 108 int len = sizeof(SA); 109 FD_ZERO(&read_set); 110 FD_ZERO(&ready); 111 FD_SET(fd_server,&read_set); 112 while(1) 113 { 114 ready = read_set; 115 tm.tv_sec=0; 116 tm.tv_usec=1000; 117 sel_ret = select(fd_server+1,&ready,NULL,NULL,&tm); 118 if(sel_ret == 0) 119 continue; 120 else if(sel_ret == -1) 121 continue; 122 else if(sel_ret == 1) 123 { 124 pNODE pnew = (pNODE)calloc(1,sizeof(NODE)); 125 memset(&my_msg,0,sizeof(MSG)); 126 recvfrom(fd_server,&my_msg,sizeof(my_msg),0,(struct sockaddr*)&(pnew->addr),&len); 127 if(my_msg.msg_type == 1) 128 { 129 add_list(&list,pnew); 130 printf("%s : %d on!!\n",inet_ntoa(pnew->addr.sin_addr),ntohs(pnew->addr.sin_port)); 131 } 132 else if(my_msg.msg_type == 3) 133 { 134 del_list(&list,&(pnew->addr)); 135 printf("%s : %d off!!\n",inet_ntoa(pnew->addr.sin_addr),ntohs(pnew->addr.sin_port)); 136 } 137 else 138 { 139 memset(buf,0,1024); 140 sprintf(buf,"\tfrom %s %d:\n%s\n",inet_ntoa(pnew->addr.sin_addr),ntohs(pnew->addr.sin_port),my_msg.msg_buf); 141 puts(buf); 142 send_msg(fd_server,buf,list); 143 } 144 } 145 } 146 return 0; 147 }
客户端实现代码如下:
1 #include <stdio.h> 2 #include <stdlib.h> 3 #include <string.h> 4 #include <sys/socket.h> 5 #include <sys/stat.h> 6 #include <sys/types.h> 7 #include <fcntl.h> 8 #include <netinet/in.h> 9 #include <arpa/inet.h> 10 #include <unistd.h> 11 typedef struct sockaddr_in SA; 12 typedef struct tag_msg 13 { 14 int msg_type; 15 int msg_len; 16 char msg_buf[1024]; 17 }MSG,*pMSG; 18 int main(int argc,char *argv[]) 19 { 20 if(argc != 2) 21 { 22 perror("参数不足!!\n"); 23 exit(1); 24 } 25 FILE *fp; 26 char ip[32]; 27 int port; 28 memset(ip,0,32); 29 fp = fopen(argv[1],"r"); 30 if(fp == NULL) 31 { 32 perror("fopen"); 33 exit(1); 34 } 35 fscanf(fp,"%s%d",ip,&port); 36 fclose(fp); 37 int fd_client; 38 int len; 39 len=sizeof(SA); 40 if((fd_client=socket(AF_INET,SOCK_DGRAM,0))==-1) 41 { 42 perror("socket"); 43 exit(1); 44 } 45 SA addr_client; 46 memset(&addr_client,0,sizeof(SA)); 47 addr_client.sin_family = AF_INET; 48 addr_client.sin_port = htons(port); 49 addr_client.sin_addr.s_addr=inet_addr(ip); 50 MSG my_msg={1,2,"on"}; 51 sendto(fd_client,&my_msg,8+my_msg.msg_len,0,(struct sockaddr*)&addr_client,sizeof(SA)); 52 if(fork() == 0) 53 { 54 if(fork() == 0) 55 { 56 char info[1024]; 57 while(memset(info,0,1024),recvfrom(fd_client,info,1024,0,NULL,NULL)>0) 58 write(1,info,strlen(info)); 59 exit(0); 60 } 61 close(fd_client); 62 exit(0); 63 } 64 wait(NULL); 65 while(memset(&my_msg,0,sizeof(MSG)),fgets(my_msg.msg_buf,1024,stdin)!=NULL) 66 { 67 my_msg.msg_type =2; 68 my_msg.msg_len = strlen(my_msg.msg_buf); 69 sendto(fd_client,&my_msg,8+my_msg.msg_len,0,(struct sockaddr*)&addr_client,sizeof(SA)); 70 } 71 my_msg.msg_type = 3; 72 my_msg.msg_len=0; 73 sendto(fd_client,&my_msg,8+my_msg.msg_len,0,(struct sockaddr*)&addr_client,sizeof(SA)); 74 close(fd_client); 75 return 0; 76 }
我相应的IP、port文件如下:
192.168.0.124 10000
郑重声明:本站内容如果来自互联网及其他传播媒体,其版权均属原媒体及文章作者所有。转载目的在于传递更多信息及用于网络分享,并不代表本站赞同其观点和对其真实性负责,也不构成任何其他建议。