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("创建管道失败!!
");
 24         exit(1);
 25     }
 26     
 27     int fd;
 28     fd = open(argv[1], O_RDONLY);
 29     if(fd == -1)
 30     {
 31         printf("open error!!
");
 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 !!
", 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 !!
", 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             else
105             {
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("创建管道失败!!
");
17         exit(1);
18     }
19     int fd;
20     fd = open(argv[1], O_WRONLY);
21     if(fd == -1)
22     {
23         printf("open error!!
");
24         exit(1);
25     }
26     char buf[128];
27     memset(buf, 0, 128);
28     sprintf(buf,"on %d
",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!!
");
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
", 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
", getpid());
60     write(fd, buf, strlen(buf));
61     close(fd);
62     unlink(name);
63     return 0;
64 }
View Code
原文地址:https://www.cnblogs.com/gjn135120/p/4009301.html