首页 > 代码库 > 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 }
客户端实现代码如下:
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 }
我相应的IP、port文件如下:
192.168.0.12410000
Linux基础——socket实现简单的群聊程序
声明:以上内容来自用户投稿及互联网公开渠道收集整理发布,本网站不拥有所有权,未作人工编辑处理,也不承担相关法律责任,若内容有误或涉及侵权可进行投诉: 投诉/举报 工作人员会在5个工作日内联系你,一经查实,本站将立刻删除涉嫌侵权内容。