日韩av黄I国产麻豆传媒I国产91av视频在线观看I日韩一区二区三区在线看I美女国产在线I麻豆视频国产在线观看I成人黄色短片

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 >

poll模型

發布時間:2025/3/21 41 豆豆
生活随笔 收集整理的這篇文章主要介紹了 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);??
  • ????????//printf("nready?is?%d\n",?nready);??
  • ????????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);//讀取客戶端socket流??
  • ????????????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模型的全部內容,希望文章能夠幫你解決所遇到的問題。

    如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。