不同于select使用三个位图来表示三个fdset的方式,poll使用一个pollfd的指针实现。
pollfd结构包含了要监视的event和发生的event,不再使用select“参数-值”传递的方式。同时,pollfd并没有最大数量限制(但是数量过大后性能也是会下降)。和select函数一样,poll返回后,需要轮询pollfd来获取就绪的描述符。
从上面看,select和poll都需要在返回后,通过遍历文件描述符来获取已经就绪的socket。事实上,同时连接的大量客户端在一时刻可能只有很少的处于就绪状态,因此随着监视的描述符数量的增长,其效率也会线性下降。
代码描述:
server.c
1 #include<stdio.h> 2 #include<string.h> 3 #include<stdlib.h> 4 #include<poll.h> 5 #include<time.h> 6 #include<unistd.h> 7 #include<sys/types.h> 8 #include<sys/socket.h> 9 #include<netinet/in.h> 10 #include<arpa/inet.h> 11 12 #define _BACKLOG_ 5 13 #define _SIZE_ 1024 14 15 void Usage(const char* proc) 16 { 17 printf("%s [ip][port]\n",proc); 18 } 19 20 int Start_sock(char* _ip,int _port) 21 { 22 int sock=socket(AF_INET,SOCK_STREAM,0); 23 if(sock<0) 24 { 25 perror("socket"); 26 exit(1); 27 } 28 struct sockaddr_in local; 29 local.sin_family=AF_INET; 30 local.sin_port=htons(_port); 31 local.sin_addr.s_addr=inet_addr(_ip); 32 socklen_t len=sizeof(local); 33 if(bind(sock,(struct sockaddr*)&local,len)<0) 34 { 35 perror("bind"); 36 exit(2); 37 } 38 if(listen(sock,_BACKLOG_)<0) 39 { 40 perror("listen"); 41 exit(3); 42 } 43 return sock; 44 } 45 int main(int argc,char* argv[]) 46 { 47 if(argc!=3) 48 { 49 Usage(argv[0]); 50 } 51 char* ip=argv[1]; 52 int port=atoi(argv[2]); 53 int listen_sock=Start_sock(ip,port); 54 55 struct sockaddr_in cli; 56 socklen_t len=sizeof(cli); 57 58 struct pollfd _pfd[_SIZE_]; 59 _pfd[0].fd=listen_sock; 60 _pfd[0].events=POLLIN; 61 _pfd[0].revents=0; 62 63 int i=0; 64 for(i=1;i<_SIZE_;++i) 65 { 66 _pfd[i].fd=-1; 67 _pfd[i].events=POLLIN; 68 _pfd[i].revents=0; 69 } 70 int done=0; 71 int timeout=5000; 72 int max=1; 73 while(!done) 74 { 75 switch(poll(_pfd,max,timeout)) 76 { 77 case 0: //timeout 78 { 79 printf("timeout...\n"); 80 break; 81 } 82 case -1: //errno 83 { 84 perror("poll"); 85 break; 86 } 87 default: 88 { 89 for(i=0;i<_SIZE_;++i) 90 { 91 if(_pfd[i].fd==listen_sock&&_pfd[i].revents & POLLIN) 92 { 93 int new_sock=accept(_pfd[i].fd,(struct sockaddr*)&cl i,&len); 94 if(new_sock<0) 95 { 96 perror("accept"); 97 continue; 98 } 99 int j=0; 100 for(j=0;j<_SIZE_;++j) 101 { 102 if(_pfd[j].fd<0) 103 { 104 _pfd[j].fd=new_sock; 105 _pfd[j].events=POLLIN; 106 _pfd[j].revents=0; 107 break; 108 } 109 } 110 if(j==_SIZE_) 111 { 112 printf("full"); 113 close(new_sock); 114 } 115 max++; 116 printf("get a new connect:%d\n",new_sock); 117 } 118 else if(_pfd[i].fd>0&&_pfd[i].revents & POLLIN) 119 { 120 char buf[1024]; 121 memset(buf,'\0',sizeof(buf)); 122 ssize_t _s=read(_pfd[i].fd,buf,sizeof(buf)-1); 123 if(_s<0) 124 { 125 perror("read"); 126 close(_pfd[i].fd); 127 } 128 else if(_s==0) 129 { 130 printf(" client close...\n"); 131 close(_pfd[i].fd); 132 } 133 else 134 { 135 buf[_s]='\0'; 136 printf("client say:%s",buf); 137 write(_pfd[i].fd,buf,sizeof(buf)-1); 138 fflush(stdout); 139 } 140 } 141 else 142 {} 143 } 144 break; 145 } 146 147 } 148 } 149 return 0; 150 }
client.c
1 #include<stdio.h> 2 #include<stdlib.h> 3 #include<string.h> 4 #include<unistd.h> 5 #include<sys/types.h> 6 #include<sys/socket.h> 7 #include<netinet/in.h> 8 #include<arpa/inet.h> 9 10 void Usage(const char* proc) 11 { 12 printf("%s [ip][port]\n",proc); 13 } 14 15 int main(int argc,char* argv[]) 16 { 17 if(argc!=3) 18 { 19 Usage(argv[0]); 20 exit(1); 21 } 22 char* ip=argv[1]; 23 int port=atoi(argv[2]); 24 int client_sock=socket(AF_INET,SOCK_STREAM,0); 25 if(client_sock<0) 26 { 27 perror("socket"); 28 exit(2); 29 } 30 struct sockaddr_in remote; 31 remote.sin_family=AF_INET; 32 remote.sin_port=htons(port); 33 remote.sin_addr.s_addr=inet_addr(ip); 34 35 if(connect(client_sock,(struct sockaddr*)&remote,sizeof(remote))<0) 36 { 37 perror("connect"); 38 exit(3); 39 } 40 char buf[1024]; 41 while(1) 42 { 43 memset(buf,'\0',sizeof(buf)); 44 printf("please input:"); 45 fflush(stdout); 46 fgets(buf,sizeof(buf)-1,stdin); 47 ssize_t _s=write(client_sock,buf,sizeof(buf)-1); 48 if(_s<0) 49 { 50 perror("write"); 51 exit(4); 52 } 53 _s=read(client_sock,buf,sizeof(buf)-1); 54 if(_s<0) 55 { 56 perror("read"); 57 exit(5); 58 } 59 else if(_s==0) 60 { 61 close(client_sock); 62 } 63 else 64 { 65 buf[_s]='\0'; 66 printf("server->client:%s",buf); 67 fflush(stdout); 68 } 69 } 70 return 0; 71 }
执行结果: