稍加改進的多路複用--poll服務器
poll是一個在select上稍加改進的多路複用版本,不久後就被功能完善的epoll所取代,它與select的區別在於select的返回經過輸入參數來返回,這樣每次都要添加要關心的文件描述符到其文件描述符集中,而poll設置了一個結構體指針參數,經過他就能夠知道狀態變化,但免不了的是依舊須要遍歷整個buf,它的大小能夠由用戶自定義,可是過於大的集合會使得服務器負擔大大加劇,而過小的集合又由於大多的socket都在等待數據到來,效率上又會下滑不少,因此poll很尷尬。
socket
poll的函數tcp
#include <poll.h> int poll(struct pollfd *fds, nfds_t nfds, int timeout); struct pollfd { int fd; /* file descriptor */ short events; /* requested events */ short revents; /* returned events */ };
poll的函數與select不同的地方就是它的fds參數,他是一個結構體指針,結構體的定義就是下面那個ide
struct pollfd,其中的events是設置的時候所要關心的時間,revents是輸出當大於零的時候便說明發生了event所設置的狀況,revents不用手動清空,他會自動清空。函數
由於和select差很少,就直接看代碼吧spa
下面是實現的一個簡單的poll版本的tcp服務器指針
由於前面的設置監聽套接字和以前的都同樣就忽略了事件
43 void PollServer(int sock) 44 { 45 int i=0; 46 int max_fd=-1; 47 struct pollfd fds[_MAX_FDS_]; 48 for(;i<_MAX_FDS_;i++) 49 { 50 fds[i].fd=-1; 51 } 52 fds[0].fd=sock; 53 max_fd=sock; 54 fds[0].events=POLLIN; //設置爲所關心的事件 55 int timeout; 56 while(1) 57 { 58 int new_sock=-1; 59 60 struct sockaddr_in client; 61 socklen_t client_len=sizeof(client); 62 63 fds[0].fd=sock; 64 fds[0].events=POLLIN; 65 timeout=5000; 66 switch(poll(fds,max_fd+1,timeout))//依然須要循環 67 { 68 case -1: 69 perror("poll"); 70 continue; 71 case 0: 72 printf("timeout\n"); 73 continue; 74 default: 75 { 76 for(i=0;i<_MAX_FDS_;i++) 77 { 78 int fd=fds[i].fd; 79 if(fd==sock&&fds[i].revents>0) //當有新的鏈接時 80 { 81 new_sock=accept(sock,(struct sockaddr*)\ 82 &client,&client_len); 83 printf("%d\n",new_sock); 84 for(i=0;i<_MAX_FDS_;i++) 85 { 86 if(fds[i].fd<0) 87 { 88 fds[i].fd=new_sock; 89 fds[i].events=POLLIN; 90 break; 91 } 92 } 93 if(i==_MAX_FDS_) 94 { 95 close(new_sock); 96 } 97 } 98 else if(fd>0&&fds[i].revents>0) //當有須要讀的數據時 99 { 100 char buf[1024]; 101 memset(buf,'\0',sizeof(buf)); 102 ssize_t size=read(fd,buf,sizeof(buf)-1); 103 if(size>0) 104 { 105 buf[size]='\0'; 106 printf("client::%s\n",buf); 107 }else if(size==0){ 108 close(fd); 109 fds[i].fd=-1; 110 fds[i].events=-1; 111 }else{ 112 perror("read"); 113 continue; 114 } 115 } 116 } 117 } 118 } 119 } 120 } 121
poll和select的區別並不大,因此很快被epoll淘汰掉了ip