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 }
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_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 }
View Code

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

192.168.0.124
10000

 

郑重声明:本站内容如果来自互联网及其他传播媒体,其版权均属原媒体及文章作者所有。转载目的在于传递更多信息及用于网络分享,并不代表本站赞同其观点和对其真实性负责,也不构成任何其他建议。