zoukankan      html  css  js  c++  java
  • 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("参数不足!!
    ");
     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!!
    ",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!!
    ",inet_ntoa(pnew->addr.sin_addr),ntohs(pnew->addr.sin_port));
    136             }
    137             else
    138             {
    139                 memset(buf,0,1024);
    140                 sprintf(buf,"	from %s %d:
    %s
    ",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("参数不足!!
    ");
    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
  • 相关阅读:
    gridview 数据绑定函数
    GridView详述
    gridview 数据绑定函数
    GridView详述
    c# windows服务
    "System.Web.Extensions, Version=1.0.61025.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35”或它的某一个依赖项。系统找不到指定的文件。
    启动网站时,IIS发生意外错误0x8ffe2740
    访问 IIS 元数据库失败
    vs2010运行时提示:无法启动程序:http://......
    realplayer、wmp 网页内嵌代码
  • 原文地址:https://www.cnblogs.com/gjn135120/p/4009355.html
Copyright © 2011-2022 走看看