首页 > 代码库 > Linux基础——socket实现简单的群聊程序

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             else138             {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 }
View Code

客户端实现代码如下:

 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_msg13 {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 }
View Code

我相应的IP、port文件如下:

192.168.0.12410000

 

Linux基础——socket实现简单的群聊程序