1. 程式人生 > >Linux IO多路複用之poll

Linux IO多路複用之poll

Linux IO多路複用之poll

前面介紹了select,今天來介紹poll,poll 是一種高階的輪詢的方法,通常用於伺服器端處理多個客戶端的請求的時候。 其作用於 select 很相似,但是較比 select 方法而言,效率更高,並且處理的連線個數不受核心的限制。 若是使用 select 來輪詢客戶端的連線,可以接受的連線個數與核心中程序所限定的可使用的檔案描述符號的個數相同。  但是使用 poll 方法並不會有這種限制。

poll函式原型:

#include <poll.h>
int poll(struct pollfd fd[], nfds_t nfds, int
timeout);

struct pollfd的結構如下:

struct pollfd {  
 int fd;        //檔案描述符  
 short events;  //要求查詢的事件掩碼  
 short revents; //返回的事件掩碼  
};  
  • 第一個引數fds是pollfd結構體指標,可以指向一個結構體陣列
  • 第二個引數 nfds 制定陣列中元素個數。
  • 第三個引數指定 poll 函式返回前等待多長時間。 INFTIM 表示永遠等待, 0 代表立即返回, > 0 等待指定數目的秒數。

程式碼:

#include"utili.h"
int main() { int sockfd; int ret; int MaxNum = 5; struct sockaddr_in seraddr,cliaddr; bzero(&seraddr,sizeof(seraddr)); seraddr.sin_family = AF_INET; seraddr.sin_addr.s_addr = htonl(INADDR_ANY); seraddr.sin_port = htons(8000); sockfd = socket(AF_INET,SOCK_STREAM,0
); ret = bind(sockfd,(struct sockaddr*)&seraddr,sizeof(seraddr)); if(ret < 0) { printf("bind error\n"); return -1; } ret = listen(sockfd,5); if(ret < 1) { printf("listen error\n"); return -1; } struct pollfd client[MaxNum]; int i = 0, maxi = 0; for(;i<MaxNum; i++) client[i].fd = -1;//初始化poll結構中的檔案描述符fd client[0].fd = sockfd;//需要監測的描述符 client[0].events = POLLIN;//普通或優先順序帶資料可讀 while(1) { //對加入poll結構體陣列所有元素進行監測 ret = poll(client,maxi+1,-1); if((client[0].events & POLLIN) == POLLIN) { int clilen = sizeof(cliaddr); int connfd = 0; // 從tcp完成連線中提取客戶端 connfd = accept(sockfd,(struct sockaddr*)&cliaddr,&clilen); // 將提取到的connfd放入poll結構體陣列中,以便於poll函式監測 for(i=1;i<MaxNum;i++) { if(client[i].fd < 0) { client[i].fd = connfd; client[i].events = POLLIN; break; } } if(i > maxi) { maxi = i; } if(--ret <= 0) { continue; } } for(i=1;i<maxi;i++) { if(client[i].fd < 0) continue; if(client[i].events & (POLLIN | POLLERR)) { int len=0; char buf[128] = ""; //接受客戶端資料 if((len = recv(client[i].fd, buf, sizeof(buf), 0)) < 0) { printf("recv error\n"); } else if(len == 0)//客戶端關閉連線 { close(client[i].fd); client[i].fd = -1; } else send(client[i].fd, buf, len, 0); //有的就緒描述符處理完了,就退出當前的for迴圈,繼續poll監測 if(--ret <= 0) break; } } } return 0; }

這段程式碼有些問題,listen返回失敗,思想是對的,有人可以改正的話,非常感謝!!!