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