生活随笔
收集整理的這篇文章主要介紹了
poll模型
小編覺得挺不錯的,現在分享給大家,幫大家做個參考.
/**
?* @AticalName: I/O多路復用技術詳解之poll模型
?* @author DK.BurNIng
?* @date 2012-8-9 下午1:46:54
?* @version V1.2
?* @comefrom?http://blog.csdn.net/bengda
?*/
poll模型
poll()系統調用是System V的多元I/O解決方案。它解決了select()的幾個不足,盡管select()仍然經常使用(多數還是出于習慣,或者打著可移植的名義):
#include <sys/poll.h>
int poll (struct pollfd *fds, unsigned int nfds, int timeout);
和select()不一樣,poll()沒有使用低效的三個基于位的文件描述符set,而是采用了一個單獨的結構體pollfd數組,由fds指針指向這個組。pollfd結構體定義如下:
#include <sys/poll.h>
struct pollfd {
int fd; /* file descriptor */
short events; /* requested events to watch */
short revents; /* returned events witnessed */
};
每一個pollfd結構體指定了一個被監視的文件描述符,可以傳遞多個結構體,指示poll()監視多個文件描述符。每個結構體的events域是監視該文件描述符的事件掩碼,由用戶來設置這個域。revents域是文件描述符的操作結果事件掩碼。內核在調用返回時設置這個域。events域中請求的任何事件都可能在revents域中返回。合法的事件如下:
POLLIN
有數據可讀。
POLLRDNORM
有普通數據可讀。
POLLRDBAND
有優先數據可讀。
POLLPRI
有緊迫數據可讀。
POLLOUT
寫數據不會導致阻塞。
POLLWRNORM
寫普通數據不會導致阻塞。
POLLWRBAND
寫優先數據不會導致阻塞。
POLLMSG
SIGPOLL消息可用。
此外,revents域中還可能返回下列事件:
POLLER
指定的文件描述符發生錯誤。
POLLHUP
指定的文件描述符掛起事件。
POLLNVAL
指定的文件描述符非法。
這些事件在events域中無意義,因為它們在合適的時候總是會從revents中返回。使用poll()和select()不一樣,你不需要顯式地請求異常情況報告。
POLLIN | POLLPRI等價于select()的讀事件,POLLOUT | POLLWRBAND等價于select()的寫事件。POLLIN等價于POLLRDNORM | POLLRDBAND,而POLLOUT則等價于POLLWRNORM。
例如,要同時監視一個文件描述符是否可讀和可寫,我們可以設置events為POLLIN | POLLOUT。在poll返回時,我們可以檢查revents中的標志,對應于文件描述符請求的events結構體。如果POLLIN事件被設置,則文件描述符可以被讀取而不阻塞。如果POLLOUT被設置,則文件描述符可以寫入而不導致阻塞。這些標志并不是互斥的:它們可能被同時設置,表示這個文件描述符的讀取和寫入操作都會正常返回而不阻塞。
timeout參數指定等待的毫秒數,無論I/O是否準備好,poll都會返回。timeout指定為負數值表示無限超時;timeout為0指示poll調用立即返回并列出準備好I/O的文件描述符,但并不等待其它的事件。這種情況下,poll()就像它的名字那樣,一旦選舉出來,立即返回。
返回值和錯誤代碼
成功時,poll()返回結構體中revents域不為0的文件描述符個數;如果在超時前沒有任何事件發生,poll()返回0;失敗時,poll()返回-1,并設置errno為下列值之一:
EBADF
一個或多個結構體中指定的文件描述符無效。
EFAULT
fds指針指向的地址超出進程的地址空間。
EINTR
請求的事件之前產生一個信號,調用可以重新發起。
EINVAL
nfds參數超出PLIMIT_NOFILE值。
ENOMEM
可用內存不足,無法完成請求。
[cpp] view plain
copy #include??<unistd.h>??#include??<sys/types.h>???????/*?basic?system?data?types?*/??#include??<sys/socket.h>??????/*?basic?socket?definitions?*/??#include??<netinet/in.h>??????/*?sockaddr_in{}?and?other?Internet?defns?*/??#include??<arpa/inet.h>???????/*?inet(3)?functions?*/????#include?<stdlib.h>??#include?<errno.h>??#include?<stdio.h>??#include?<string.h>??????#include?<poll.h>?/*?poll?function?*/??#include?<limits.h>????#define?MAXLINE?10240????#ifndef?OPEN_MAX??#define?OPEN_MAX?40960??#endif????void?handle(struct?pollfd*?clients,?int?maxClient,?int?readyClient);????int??main(int?argc,?char?**argv)??{??????int?servPort?=?6888;??????int?listenq?=?1024;??????int?listenfd,?connfd;??????struct?pollfd?clients[OPEN_MAX];??????int??maxi;??????socklen_t?socklen?=?sizeof(struct?sockaddr_in);??????struct?sockaddr_in?cliaddr,?servaddr;??????char?buf[MAXLINE];??????int?nready;????????bzero(&servaddr,?socklen);??????servaddr.sin_family?=?AF_INET;??????servaddr.sin_addr.s_addr?=?htonl(INADDR_ANY);??????servaddr.sin_port?=?htons(servPort);????????listenfd?=?socket(AF_INET,?SOCK_STREAM,?0);??????if?(listenfd?<?0)?{??????????perror("socket?error");??????}????????int?opt?=?1;??????if?(setsockopt(listenfd,?SOL_SOCKET,?SO_REUSEADDR,?&opt,?sizeof(opt))?<?0)?{??????????perror("setsockopt?error");??????}????????if(bind(listenfd,?(struct?sockaddr?*)?&servaddr,?socklen)?==?-1)?{??????????perror("bind?error");??????????exit(-1);??????}??????if?(listen(listenfd,?listenq)?<?0)?{??????????perror("listen?error");??????????}????????clients[0].fd?=?listenfd;??????clients[0].events?=?POLLIN;??????int?i;??????for?(i?=?1;?i<?OPEN_MAX;?i++)???????????clients[i].fd?=?-1;???????maxi?=?listenfd?+?1;????????printf("pollechoserver?startup,?listen?on?port:%d\n",?servPort);??????printf("max?connection?is?%d\n",?OPEN_MAX);????????for?(?;?;?)??{??????????nready?=?poll(clients,?maxi?+?1,?-1);????????????????????if?(nready?==?-1)?{??????????????perror("poll?error");??????????}??????????if?(clients[0].revents?&?POLLIN)?{??????????????connfd?=?accept(listenfd,?(struct?sockaddr?*)?&cliaddr,?&socklen);??????????????sprintf(buf,?"accept?form?%s:%d\n",?inet_ntoa(cliaddr.sin_addr),?cliaddr.sin_port);??????????????printf(buf,?"");????????????????for?(i?=?0;?i?<?OPEN_MAX;?i++)?{??????????????????if?(clients[i].fd?==?-1)?{??????????????????????clients[i].fd?=?connfd;??????????????????????clients[i].events?=?POLLIN;??????????????????????break;??????????????????}??????????????}????????????????if?(i?==?OPEN_MAX)?{??????????????????fprintf(stderr,?"too?many?connection,?more?than?%d\n",?OPEN_MAX);??????????????????close(connfd);??????????????????continue;??????????????}????????????????if?(i?>?maxi)??????????????????maxi?=?i;????????????????--nready;??????????}????????????handle(clients,?maxi,?nready);??????}??}????void?handle(struct?pollfd*?clients,?int?maxClient,?int?nready)?{??????int?connfd;??????int?i,?nread;??????char?buf[MAXLINE];????????if?(nready?==?0)??????????return;????????for?(i?=?1;?i<?maxClient;?i++)?{??????????connfd?=?clients[i].fd;??????????if?(connfd?==?-1)???????????????continue;??????????if?(clients[i].revents?&?(POLLIN?|?POLLERR))?{??????????????nread?=?read(connfd,?buf,?MAXLINE);??????????????if?(nread?<?0)?{??????????????????perror("read?error");??????????????????close(connfd);??????????????????clients[i].fd?=?-1;??????????????????continue;??????????????}??????????????if?(nread?==?0)?{??????????????????printf("client?close?the?connection");??????????????????close(connfd);??????????????????clients[i].fd?=?-1;??????????????????continue;??????????????}????????????????write(connfd,?buf,?nread);??????????????if?(--nready?<=?0)??????????????????break;??????????}??????}??}?
總結
以上是生活随笔為你收集整理的poll模型的全部內容,希望文章能夠幫你解決所遇到的問題。
如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。