首页 > 代码库 > Linux基础——通过select实现简单的服务器与客户端

Linux基础——通过select实现简单的服务器与客户端

在这里,我们还是需要一个管道,只不过,我们只需这一个管道,即可知道,客户端有哪些上线、对话、下线等。

服务器端的实现代码如下:

  1 #include <stdio.h>  2 #include <stdlib.h>  3 #include <string.h>  4 #include <sys/stat.h>  5 #include <sys/types.h>  6 #include <fcntl.h>  7 #include <sys/time.h>  8 #include <sys/select.h>  9 #include <errno.h> 10 #define ON 1 11 #define OFF 0 12 int errno; 13 typedef struct tag 14 { 15     int id; 16     int fd; 17     int type; 18 }NODE; 19 int main(int argc, const char *argv[]) 20 { 21     if(mkfifo(argv[1], 0666) == -1) 22     { 23         printf("创建管道失败!!\n"); 24         exit(1); 25     } 26      27     int fd; 28     fd = open(argv[1], O_RDONLY); 29     if(fd == -1) 30     { 31         printf("open error!!\n"); 32         exit(1); 33     } 34     NODE list[1024]; 35     int i; 36     for(i = 0; i< 1024; i ++) 37     { 38         list[i].id = 0; 39         list[i].type = OFF; 40         list[i].fd = 0; 41     } 42     fd_set readset, ready; 43     FD_ZERO(&readset); 44     FD_ZERO(&ready); 45     FD_SET(fd, &readset); 46     struct timeval tm; 47     char buf[128]; 48     int ret; 49     while(1) 50     { 51         ready = readset; 52         tm.tv_sec = 0; 53         tm.tv_usec = 1000; 54         ret = select(fd + 1, &ready, NULL, NULL, &tm); 55         if(ret == 0) 56             continue; 57         else if(ret == -1) 58         { 59             if(errno == EINTR) 60                 continue; 61             break; 62         } 63         else 64         { 65             memset(buf, 0, 128); 66             read(fd, buf, 128); 67             if(strncmp(buf, "on", 2) == 0) 68             { 69                 int sfd; 70                 char name[128]; 71                 memset(name, 0, 128); 72                 sscanf(buf + 3, "%d", &sfd); 73                 printf(" %d is on !!\n", sfd); 74                 sprintf(name, "%d.fifo", sfd); 75                 int index; 76                 for(index = 0; index < 1024; index ++) 77                 { 78                     if(list[index].type == OFF) 79                     { 80                         list[index].id = sfd; 81                         list[index].fd = open(name, O_WRONLY); 82                         list[index].type = ON; 83                         break; 84                     } 85                 } 86             } 87             else if(strncmp(buf, "off", 3) == 0) 88             { 89                 int sfd; 90                 sscanf(buf + 4, "%d", &sfd); 91                 printf("%d is off !!\n", sfd); 92                 int index; 93                 for(index = 0; index <1024; index ++) 94                 { 95                     if(list[index].id == sfd) 96                     { 97                         close(list[index].fd); 98                         list[index].id = 0; 99                         list[index].type = OFF;100                         break;101                     }102                 }103             }104             else105             {106                 int sfd;107                 sscanf(buf + 5, "%d", &sfd);108                 int index;109                 for(index = 0; index < 1024; index ++)110                 {111                     if(list[index].type == ON && list[index].id != sfd)112                         write(list[index].fd, buf, strlen(buf));113                 }114             }115         }116     }117     close(fd);118     unlink(argv[1]);119     return 0;120 }
View Code

在这里,当ret = -1时,我们需要判断errno是否由信号中断引起的,如果是由于人为的退出,那么程序将退出,

如果是由于信号中断,程序将再次连接信号,等待数据。

客户端的实现代码如下:

 1 #include <stdio.h> 2 #include <stdlib.h> 3 #include <string.h> 4 #include <sys/stat.h> 5 #include <sys/time.h> 6 #include <sys/types.h> 7 #include <sys/select.h> 8 #include <fcntl.h> 9 int main(int argc, const char *argv[])10 {11     char name[128];12     memset(name, 0, 128);13     sprintf(name, "%d.fifo", getpid());14     if(mkfifo(name, 0666) == -1)15     {16         printf("创建管道失败!!\n");17         exit(1);18     }19     int fd;20     fd = open(argv[1], O_WRONLY);21     if(fd == -1)22     {23         printf("open error!!\n");24         exit(1);25     }26     char buf[128];27     memset(buf, 0, 128);28     sprintf(buf,"on %d\n",getpid());29     write(fd, buf, strlen(name));30     int sfd;31     sfd = open(name, O_RDONLY);32     if(sfd == -1)33     {34         printf("open error!!\n");35         exit(1);36     }37     if(fork() == 0)38     {39         if(fork() == 0)40         {41             close(fd);42             while(memset(buf, 0, 128), read(sfd, buf, 128))43                 printf(" >> %s\n", buf);44             close(sfd);45             exit(1);46         }47         exit(1);48     }49     wait(NULL);50     close(sfd);51     while(memset(buf, 0, 128), fgets(buf, 128, stdin) != NULL)52     {53         char msg[128];54         memset(msg, 0, 128);55         sprintf(msg, "from %d: %s",getpid(), buf);56         write(fd, msg, strlen(msg));57     }58     memset(buf, 0, 128);59     sprintf(buf, "off %d\n", getpid());60     write(fd, buf, strlen(buf));61     close(fd);62     unlink(name);63     return 0;64 }
View Code

 

Linux基础——通过select实现简单的服务器与客户端