I O多路轉接之poll

2021-08-02 14:52:59 字數 3891 閱讀 6048

poll()函式:這個函式是某些linux系統提供的用於執行與select()函式同等功能的函式,下面是這個函式的宣告:

#include 

int poll(struct pollfd fds, nfds_t nfds, int timeout);

引數說明:

fds:是乙個struct pollfd結構型別的陣列,用於存放需要檢測其狀態的socket描述符;每當呼叫這個函式之後,系統不會清空這個陣列,操作起來比較方便;特別是對於socket連線比較多的情況下,在一定程度上可以提高處理的效率;這一點與select()函式不同,呼叫select()函式之後,select()函式會清空它所檢測的socket描述符集合,導致每次呼叫select()之前都必須把socket描述符重新加入到待檢測的集合中;因此,select()函式適合於只檢測乙個socket描述符的情況,而poll()函式適合於大量socket描述符的情況;

nfds:nfds_t型別的引數,用於標記陣列fds中的結構體元素的總數量;

timeout:是poll函式呼叫阻塞的時間,單位:毫秒;

返回值:

0:陣列fds中準備好讀、寫或出錯狀態的那些socket描述符的總數量;

==0:陣列fds中沒有任何socket描述符準備好讀、寫,或出錯;此時poll超時,超時時間是timeout毫秒;換句話說,如果所檢測的socket描述符上沒有任何事件發生的話,那麼poll()函式會阻塞timeout所指定的毫秒時間長度之後返回,如果timeout==0,那麼poll() 函式立即返回而不阻塞,如果timeout==inftim,那麼poll() 函式會一直阻塞下去,直到所檢測的socket描述符上的感興趣的事件發生是才返回,如果感興趣的事件永遠不發生,那麼poll()就會永遠阻塞下去;

-1: poll函式呼叫失敗,同時會自動設定全域性變數errno;

poll()接受乙個指向結構struct pollfd列表的指標,其中包括了你想監測的檔案描述符和事件,結構體如下:

struct pollfd ;
poll與select不同,通過乙個pollfd陣列向核心傳遞需要關注的事件,故沒有描述符個數的限制, 

pollfd中的events欄位和revents分別用於標示關注的事件和發生的事件,故pollfd陣列只需要被初始化一次。

poll的實現機制與select類似,其對應核心中的sys_poll,只不過poll向核心傳遞pollfd陣列,然後對pollfd中的每個描述符進行poll,相比處理fdset來說,poll效率更高。 

poll返回後,需要對pollfd中的每個元素檢查其revents值,來得指事件是否發生。

poll的優點:

1)poll() 不要求開發者計算最大檔案描述符加一的大小。

2)poll() 在應付大數目的檔案描述符的時候相比於select速度更快

3)它沒有最大連線數的限制,原因是它是基於鍊錶來儲存的。

poll的缺點:

1)大量的fd的陣列被整體複製於使用者態和核心位址空間之間,而不管這樣的複製是不是有意義。

2)與select一樣,poll返回後,需要輪詢pollfd來獲取就緒的描述符

利用poll編寫基於tcp的伺服器:

伺服器端**:

#include

#include

#include

#include

#include

#include

#include

#include

static

void use(char* proc)

int startup(const

char* ip,int port)

int opt = 1;

setsockopt(sock,sol_socket,so_reuseaddr,&opt,sizeof(opt));

struct sockaddr_in local;

local.sin_family = af_inet;

local.sin_port = htons(port);

local.sin_addr.s_addr = inet_addr(ip);

if(bind(sock,(struct sockaddr*)&local,sizeof(local))<0)

if(listen(sock,10)<0)

return sock;

}int main(int argc,char* argv)

int listen_sock = startup(argv[1],atoi(argv[2]));

struct pollfd _poll[64];

_poll[0].fd = listen_sock;

_poll[0].events = pollin;

_poll[0].revents = 0;

//int poll_len = sizeof(_poll)/sizeof(_poll[0]);

int i = 1;

for(;i<64;i++)

int maxfd = 1;

while(1)

printf("get a new client:%s:%d\n",inet_ntoa(client.sin_addr), ntohs(client.sin_port));

int j =1;

for(;j<64;j++)

}if(j==64)

if(j==maxfd)

}//if

else

if(_poll[i].fd != listen_sock && _poll[i].revents & pollin)

else

if(s<0)

else

if(s==0)

}}//for

}break;

}} for(i=0;i<64;++i)

return

0;}

客戶端**:

#include

#include

#include

#include

#include

#include

#include

#include

#include

static

void use(const

char* proc)

int main(int argc,char* argv)

int sock = socket(af_inet,sock_stream,0);

if(sock<0)

struct sockaddr_in peer;

peer.sin_family = af_inet;

peer.sin_port = htons(atoi(argv[2]));

peer.sin_addr.s_addr = inet_addr(argv[1]);

if(connect(sock,(struct sockaddr*)&peer,sizeof(peer))<0)

char buf[1024];

while(1)

buf[s-1]=0;

write(sock,buf,strlen(buf));

printf("server echo#%s\n",buf);

}close(sock);

return

0;}

執行結果示例:

IO多路轉接之poll

poll函式 include int poll struct pollfd fds,nfds t nfds,int timeout pollfd結構 struct pollfd fds poll函式監聽的結構列表 nfds fds陣列的長度。timeout 喚醒時間 pollfd結構體events常...

I O多路轉接(二) poll函式

第二篇介紹poll函式,不說廢話直接來看函式。int poll struct pollfd fds,nfds t nfds,int timeout 返回值 大於0,準備就緒的file descriptor數量 等於0,超時 小於0,出錯。引數 fds struct pollfd nfds 關心的fd...

I O多路轉接之poll伺服器

函式說明 include int poll struct pollfd fds,nfds t nfds,int timeout 引數說明 fds 是乙個struct pollfd結構型別的陣列,用於存放需要檢測其狀態的socket描述符 每當呼叫這個函式之後,系統不會清空這個陣列,操作起來比較方便 ...