日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當(dāng)前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

poll模型

發(fā)布時間:2025/3/21 编程问答 38 豆豆
生活随笔 收集整理的這篇文章主要介紹了 poll模型 小編覺得挺不錯的,現(xiàn)在分享給大家,幫大家做個參考.

/**
?* @AticalName: I/O多路復(fù)用技術(shù)詳解之poll模型
?* @author DK.BurNIng
?* @date 2012-8-9 下午1:46:54
?* @version V1.2
?* @comefrom?http://blog.csdn.net/bengda
?*/

poll模型
poll()系統(tǒng)調(diào)用是System V的多元I/O解決方案。它解決了select()的幾個不足,盡管select()仍然經(jīng)常使用(多數(shù)還是出于習(xí)慣,或者打著可移植的名義):


#include <sys/poll.h>
int poll (struct pollfd *fds, unsigned int nfds, int timeout);

和select()不一樣,poll()沒有使用低效的三個基于位的文件描述符set,而是采用了一個單獨(dú)的結(jié)構(gòu)體pollfd數(shù)組,由fds指針指向這個組。pollfd結(jié)構(gòu)體定義如下:

#include <sys/poll.h>

struct pollfd {
int fd; /* file descriptor */
short events; /* requested events to watch */
short revents; /* returned events witnessed */
};

每一個pollfd結(jié)構(gòu)體指定了一個被監(jiān)視的文件描述符,可以傳遞多個結(jié)構(gòu)體,指示poll()監(jiān)視多個文件描述符。每個結(jié)構(gòu)體的events域是監(jiān)視該文件描述符的事件掩碼,由用戶來設(shè)置這個域。revents域是文件描述符的操作結(jié)果事件掩碼。內(nèi)核在調(diào)用返回時設(shè)置這個域。events域中請求的任何事件都可能在revents域中返回。合法的事件如下:
POLLIN
有數(shù)據(jù)可讀。
POLLRDNORM
有普通數(shù)據(jù)可讀。
POLLRDBAND
有優(yōu)先數(shù)據(jù)可讀。
POLLPRI
有緊迫數(shù)據(jù)可讀。
POLLOUT
寫數(shù)據(jù)不會導(dǎo)致阻塞。
POLLWRNORM
寫普通數(shù)據(jù)不會導(dǎo)致阻塞。
POLLWRBAND
寫優(yōu)先數(shù)據(jù)不會導(dǎo)致阻塞。
POLLMSG
SIGPOLL消息可用。

此外,revents域中還可能返回下列事件:
POLLER
指定的文件描述符發(fā)生錯誤。
POLLHUP
指定的文件描述符掛起事件。
POLLNVAL
指定的文件描述符非法。

這些事件在events域中無意義,因?yàn)樗鼈冊诤线m的時候總是會從revents中返回。使用poll()和select()不一樣,你不需要顯式地請求異常情況報(bào)告。
POLLIN | POLLPRI等價(jià)于select()的讀事件,POLLOUT | POLLWRBAND等價(jià)于select()的寫事件。POLLIN等價(jià)于POLLRDNORM | POLLRDBAND,而POLLOUT則等價(jià)于POLLWRNORM。
例如,要同時監(jiān)視一個文件描述符是否可讀和可寫,我們可以設(shè)置events為POLLIN | POLLOUT。在poll返回時,我們可以檢查revents中的標(biāo)志,對應(yīng)于文件描述符請求的events結(jié)構(gòu)體。如果POLLIN事件被設(shè)置,則文件描述符可以被讀取而不阻塞。如果POLLOUT被設(shè)置,則文件描述符可以寫入而不導(dǎo)致阻塞。這些標(biāo)志并不是互斥的:它們可能被同時設(shè)置,表示這個文件描述符的讀取和寫入操作都會正常返回而不阻塞。
timeout參數(shù)指定等待的毫秒數(shù),無論I/O是否準(zhǔn)備好,poll都會返回。timeout指定為負(fù)數(shù)值表示無限超時;timeout為0指示poll調(diào)用立即返回并列出準(zhǔn)備好I/O的文件描述符,但并不等待其它的事件。這種情況下,poll()就像它的名字那樣,一旦選舉出來,立即返回。
返回值和錯誤代碼
成功時,poll()返回結(jié)構(gòu)體中revents域不為0的文件描述符個數(shù);如果在超時前沒有任何事件發(fā)生,poll()返回0;失敗時,poll()返回-1,并設(shè)置errno為下列值之一:
EBADF
一個或多個結(jié)構(gòu)體中指定的文件描述符無效。
EFAULT
fds指針指向的地址超出進(jìn)程的地址空間。
EINTR
請求的事件之前產(chǎn)生一個信號,調(diào)用可以重新發(fā)起。
EINVAL
nfds參數(shù)超出PLIMIT_NOFILE值。
ENOMEM
可用內(nèi)存不足,無法完成請求。


[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);//響應(yīng)客戶端????
  • ????????????if?(--nready?<=?0)//沒有連接需要處理,退出循環(huán)??
  • ????????????????break;??
  • ????????}??
  • ????}??
  • }?
  • 總結(jié)

    以上是生活随笔為你收集整理的poll模型的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。

    如果覺得生活随笔網(wǎng)站內(nèi)容還不錯,歡迎將生活随笔推薦給好友。