Linux网络编程---I/O复用模型之poll
https://blog.csdn.net/men_wen/article/details/53456474
Linux網(wǎng)絡(luò)編程—I/O復(fù)用模型之poll
1.函數(shù)poll
poll系統(tǒng)調(diào)用和select類似,也是在指定時間內(nèi)輪詢一定數(shù)量的文件描述符,以測試其中是否有就緒者。
#include <poll.h>int poll(struct pollfd *fds, nfds_t nfds, int timeout); //返回值:若成功,返回就緒的描述符個數(shù),若超時則為0,若出錯則為-1- fds是指向一個pollfd結(jié)構(gòu)第一個元素的指針。每一個元素都是pollfd結(jié)構(gòu)類型,用于測試某個給定描述符fd的條件
要測試的條件在events中指定,函數(shù)相應(yīng)的revents成員返回該描述符的狀態(tài),一個為調(diào)用值,一個為返回結(jié)果,這與select的傳入傳出參數(shù)不同。?
events和revents可以設(shè)置以下常量的一個或多個的按位或結(jié)果:
- out指定poll函數(shù)返回前等待多長時間,它是一個指定應(yīng)等待毫秒數(shù)的正值。
|timeout值|說明|?
|:-:|:-:|?
|-1|永遠等待|?
|0|立即返回,不阻塞進程|?
|>0|等待指定數(shù)目的毫秒數(shù)|
- nfds 是監(jiān)控數(shù)組中有多少文件描述符需要被監(jiān)控
如果我們不關(guān)心某個特定的描述符,那么可以把與它對應(yīng)的pollfd結(jié)構(gòu)的fd成員設(shè)置為一個負值。poll函數(shù)會忽略這樣的pollfd結(jié)構(gòu)的events成員,返回時將其revents成員的值置為0。
select模型最多可以創(chuàng)建一個1024個文件描述符大小的集合,這是因為受到fd_set的固定數(shù)據(jù)類型的限制,而poll則沒有這樣的問題,因為分配一個pollfd結(jié)構(gòu)的數(shù)組并把數(shù)組中的元素通知內(nèi)核稱為調(diào)用者的責(zé)任。但是poll模型任然使用的是輪詢模型,效率比較低下。
2. poll模型實現(xiàn)
2.1 服務(wù)器端
#include "wrap.h" #include <poll.h> #include <limits.h> #include <sys/stropts.h>#define MAXLINE 1024 #define INFTIM -1 #define OPEN_MAX 3000 int main(int argc, char *argv[]) {int i, maxi, listenfd, connfd, sockfd;int nready;ssize_t n;char buf[MAXLINE];socklen_t clilen;struct pollfd client[OPEN_MAX];struct sockaddr_in clientaddr;listenfd = start_ser(argv[1], argv[2]);//監(jiān)聽文件描述符 該函數(shù)參考selectclient[0].fd = listenfd;//將監(jiān)聽文件描述符加入pollfd數(shù)組中client[0].events = POLLIN;//設(shè)置為輸入可讀for(i = 1; i < OPEN_MAX; i++){//初始化結(jié)構(gòu)體數(shù)組client[i].fd = -1;}maxi = 0;while(1){nready = poll(client, maxi+1, INFTIM); //阻塞等待注冊時間發(fā)生if(client[0].revents & POLLIN){//當(dāng)監(jiān)聽文件描述符響應(yīng)有新連接請求clilen = sizeof(clientaddr);connfd = Accept(listenfd, (struct sockaddr *)&clientaddr, &clilen);//接受新客戶for(i = 1; i < OPEN_MAX; i++){if(client[i].fd < 0){client[i].fd = connfd; //把新客戶的文件描述符加入數(shù)組break;}}if(i == OPEN_MAX){ //連接新客戶上限Close(connfd);perr_exit("too many clients");}client[i].events = POLLIN; //新客戶端的處理事件if(i > maxi){maxi = i; //更新最大值}if(--nready == 0){ //沒有可讀的描述符跳過本次循環(huán)continue;}}for(i = 1; i <= maxi; i++){ //請求所有客戶端的數(shù)據(jù)if((sockfd = client[i].fd) < 0){continue;}if(client[i].revents & POLLIN){ //POLLIN事件發(fā)生memset(buf, '\0', MAXLINE);if((n = Read(sockfd, buf, MAXLINE-1)) < 0){if(errno == ECONNRESET){ //當(dāng)客戶端發(fā)送resetClose(sockfd);client[i].fd = -1;}else{perr_exit("read err");}}else if(n == 0){Close(sockfd);client[i].fd = -1;}else{printf("client : %s\n", buf);}if(--nready == 0){ //沒有可讀的描述符跳過本次循環(huán)break;}}}}Close(connfd);Close(listenfd);return 0; }2.2客戶端
#include "wrap.h"int main(int argc, char *argv[]) {struct sockaddr_in serveraddr;int connfd;connfd = Socket(AF_INET, SOCK_STREAM, 0);bzero(&serveraddr, sizeof(serveraddr));serveraddr.sin_family = AF_INET;serveraddr.sin_port = htons(atoi(argv[2]));inet_pton(AF_INET, argv[1], &serveraddr.sin_addr);Connect(connfd, (struct sockaddr *)&serveraddr, sizeof(serveraddr));char buf[1024];while((fgets(buf, 1024, stdin)) != NULL){Write(connfd, buf, strlen(buf));}Close(connfd);return 0; }2.3程序測試結(jié)果
創(chuàng)作挑戰(zhàn)賽新人創(chuàng)作獎勵來咯,堅持創(chuàng)作打卡瓜分現(xiàn)金大獎
總結(jié)
以上是生活随笔為你收集整理的Linux网络编程---I/O复用模型之poll的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 和同学solo,我盲僧他狗头,三头一塔,
- 下一篇: 成都欢乐谷忘了带残疾证,但有照片,可以进