I/O多路轉接之poll 函數

http://blog.csdn.net/li_ning_/article/details/52167224

poll

一、poll()函數:

這個函數是某些Unix系統提供的用于執行與select()函數同等功能的函數,自認為poll和select大同小異,下面是這個函數的聲明:

[cpp]?view plain?copy
  1. #include?<poll.h>??
  2. ??
  3. int?poll(struct?pollfd?*fds,?nfds_t?nfds,?int?timeout);??

參數:

1.第一個參數:一個結構數組,struct pollfd:

? ? ? ? fds:是一個struct pollfd結構類型的數組,每個數組元素都是一個pollfd結構,用于指定測試某個給定描述字fd的條件。存放需要檢測其狀態的Socket描述符;每當調用這個函數之后,系統不會清空這個數組,操作起來比較方便;特別是對于socket連接比較多的情況下,在一定程度上可以提高處理的效率;這一點與select()函數不同,調用select()函數之后,select()函數會清空它所檢測的socket描述符集合,導致每次調用select()之前都必須把socket描述符重新加入到待檢測的集合中;因此,select()函數適合于只檢測一個socket描述符的情況,而poll()函數適合于大量socket描述符的情況

結構如下:

[cpp]?view plain?copy
  1. struct?pollfd{??
  2.  int?fd;??????????//文件描述符??
  3.  short?events;????//請求的事件??
  4.  short?revents;???//返回的事件??
  5.  };??

  events和revents是通過對代表各種事件的標志進行邏輯或運算構建而成的。events包括要監視的事件(就是我需要關注的時間,是讀?是寫?還是出錯?)poll用已經發生的事件填充revents。poll函數通過在revents中設置標志肌膚POLLHUP、POLLERR和POLLNVAL來反映相關條件的存在。不需要在events中對于這些標志符相關的比特位進行設置。如果fd小于0, 則events字段被忽略,而revents被置為0.標準中沒有說明如何處理文件結束。文件結束可以通過revents的標識符POLLHUN或返回0字節的常規讀操作來傳達。即使POLLIN或POLLRDNORM指出還有數據要讀,POLLHUP也可能會被設置。因此,應該在錯誤檢驗之前處理正常的讀操作。

poll函數的事件標志符值:

常量說明
POLLIN普通或優先級帶數據可讀
POLLRDNORM普通數據可讀
POLLRDBAND優先級帶數據可讀
POLLPRI高優先級數據可讀
POLLOUT普通數據可寫
POLLWRNORM普通數據可寫
POLLWRBAND優先級帶數據可寫
POLLERR發生錯誤
POLLHUP發生掛起
POLLNVAL描述字不是一個打開的文件

? 注意:

? ? ? ? 1)后三個只能作為描述字的返回結果存儲在revents中,而不能作為測試條件用于events中。

  2)第二個參數nfds:要監視的描述符的數目。

  3)最后一個參數timeout:是一個用毫秒表示的時間,是指定poll在返回前沒有接收事件時應該等待的時間。如果? 它的值為-1,poll就永遠都不會超時。如果整數值為32個比特,那么最大的超時周期大約是30分鐘。?

timeout值說明
INFTIM永遠等待
0立即返回,不阻塞進程
>0
等待指定數目的毫秒數


如果是對一個描述符上的多個事件感興趣的話,可以把這些常量標記之間進行按位或運算就可以了;

比如:

對socket描述符fd上的讀、寫、異常事件感興趣,就可以這樣做:

[cpp]?view plain?copy
  1. struct?pollfd??fds;??
  2. ??
  3. fds[index].events=POLLIN?|?POLLOUT?|?POLLERR;??

當 poll()函數返回時,要判斷所檢測的socket描述符上發生的事件,可以這樣做:

[cpp]?view plain?copy
  1. struct?pollfd??fds;??
  2. ??
  3. //檢測可讀TCP連接請求:??
  4. if((fds[nIndex].revents?&?POLLIN)?==?POLLIN)??
  5. {??
  6. <span?style="white-space:pre">????</span>//接收數據,調用accept()接收連接請求??
  7. }??
  8. ??
  9. //檢測可寫:??
  10. if((fds[nIndex].revents?&?POLLOUT)?==?POLLOUT)??
  11. {??
  12. <span?style="white-space:pre">????</span>//發送數據??
  13. }??
  14. ??
  15. //檢測異常:??
  16. if((fds[nIndex].revents?&?POLLERR)?==?POLLERR)??
  17. {??
  18. <span?style="white-space:pre">????</span>//異常處理??
  19. }??
二、實例TCP服務器的服務器程序

[cpp]?view plain?copy
  1. #include?<stdio.h>??
  2. #include?<stdlib.h>??
  3. #include?<unistd.h>??
  4. #include?<sys/socket.h>??
  5. #include?<sys/types.h>??
  6. #include?<netinet/in.h>??
  7. #include?<netdb.h> ??
  8. #include?<string.h>??
  9. #include?<errno.h>??
  10. #include?<poll.h>???//for?poll??
  11. ??
  12. #define?LISTENQ?1024??
  13. #define?MAXLINE?1024??
  14. #define?OPEN_MAX?50000??
  15. ??
  16. #ifndef?INFTIM???
  17. #define?INFTIM?-1???
  18. #endif???????????????
  19. ??
  20. int?start_up(char*?ip,int?port)??//創建一個套接字,綁定,檢測服務器??
  21. {??
  22. ??//sock??
  23. ??//1.創建套接字??
  24. ??int?sock=socket(AF_INET,SOCK_STREAM,0);?????
  25. ??if(sock<0)??
  26. ??{??
  27. ??????perror("sock");??
  28. ??????exit(0);??
  29. ??}??
  30. ????
  31. ??//2.填充本地?sockaddr_in?結構體(設置本地的IP地址和端口)??
  32. ??struct?sockaddr_in?local;?????????
  33. ??local.sin_port=htons(port);??
  34. ??local.sin_family=AF_INET;??
  35. ??local.sin_addr.s_addr=inet_addr(ip);??
  36. ??
  37. ??//3.bind()綁定??
  38. ??if(bind(sock,(struct?sockaddr*)&local,sizeof(local))<0)???
  39. ??{??
  40. ??????perror("bind");??
  41. ??????exit(1);??
  42. ??}??
  43. ??//4.listen()監聽?檢測服務器??
  44. ??if(listen(sock,back_log)<0)??
  45. ??{??
  46. ??????perror("sock");??
  47. ??????exit(1);??
  48. ??}??
  49. ??return?sock;????//這樣的套接字返回??
  50. }??
  51. ??????
  52. int?main(int?argc,?char?*argv[])??
  53. {??
  54.   int?i,?maxi,?connfd,?sockfd;??
  55.   int?nready;??
  56.   ssize_t?n;??
  57.   socklen_t?clilen;??
  58. ??
  59.   struct?sockaddr_in?servaddr;??
  60. ????socklen_t?len=sizeof(servaddr);???
  61. ??
  62.  ??char?buf[BUFSIZ];??
  63. ????struct?pollfd?client[OPEN_MAX];?//?用于poll函數第一個參數的數組,存放每次的文件描述符個數??
  64.   if(?argc?!=?3?)??
  65. ????{??
  66.   ?????printf("Please?input?%s?<hostname>\n",?argv[0]);??
  67. ?????exit(2);??
  68. ????}??
  69. ??
  70. ????????int?listenfd=start_up(argv[1],argv[2]);??????//創建一個綁定了本地?ip?和端口號的套接字描述符??
  71. ??????????
  72.   ????client[0].fd?=?listenfd;?????????//將數組中的第一個元素設置成監聽描述字??
  73.   ????client[0].events?=?POLLIN;???????//將測試條件設置成普通或優先級帶數據可讀(感興趣的事件讀、寫、出錯),此處書中為POLLRDNORM,*/??
  74. ????????client[0].revents?=?0;???????????//真正發生的事件??
  75. ??
  76.   ????for(i?=?1;i?<?OPEN_MAX;?++i)?????//數組中的其它元素將暫時設置成不可用??
  77. ????????{??
  78. ????????????client[i].fd?=?-1;??
  79. ????????}??
  80. ??????????
  81.   ????maxi?=?0;??
  82.  ??????while(1)??
  83.   ????{??
  84.   ???????nready?=?poll(client,?maxi+1,INFTIM);??????????//將進程阻塞在poll上??
  85.   ???????if(?client[0].revents?&?POLLIN)????????????????//先測試監聽描述字??
  86.   ???????{??
  87. ????????????????connfd?=?accept(listenfd,(struct?sockaddr*)&servaddr,?&clilen);??
  88. ??
  89.   ????????????for(i?=?1;?i?<?OPEN_MAX;?++i)??
  90. ????????????????{??
  91. ????????????????????if(?client[i].fd?<?0?)??
  92.   ????????????????{??
  93.  ?????????????????????client[i].fd?=?connfd;??????//將新連接加入到測試數組中??
  94.   ???????????????????client[i].events?=?POLLIN;??//POLLRDNORM;?測試條件普通數據可讀??
  95.  ?????????????????????break;??
  96.   ????????????????}??
  97.   ??????????????if(?i?==?OPEN_MAX?)??
  98.  ???????????????{??
  99.   ??????????????????????printf("too?many?clients");?//連接的客戶端太多了,都達到最大值了??
  100.  ???????????????????exit(1);??
  101.   ??????????????}??
  102. ??
  103.   ??????????????if(?i?>?maxi?)??
  104.   ??????????????????maxi?=?i;????????//maxi記錄的是數組元素的個數??
  105. ??
  106.   ??????????????if(?--nready?<=?0?)??
  107.   ??????????????????continue;????????????//如果沒有可讀的描述符了,就重新監聽連接??
  108. ????????????????}??
  109.   ????????}??
  110. ??
  111.   ????????for(i?=?1;?i?<=?maxi;?i++)??//測試除監聽描述字以后的其它連接描述字??
  112.   ????????{??
  113. ????????????????if(?(sockfd?=?client[i].fd)?<?0)?//如果當前描述字不可用,就測試下一個??
  114.   ????????????????continue;??
  115. ??
  116.   ????????????if(client[i].revents?&?(POLLIN?|?POLLERR))//如果當前描述字返回的是普通數據可讀或出錯條件??
  117.   ????????????{??
  118.  ????????????????if(?(n?=?read(sockfd,?buf,?MAXLINE))?<?0)?//從套接口中讀數據??
  119.   ???????????????{??
  120.   ????????????????????if(?errno?==?ECONNRESET)?//如果連接斷開,就關閉連接,并設當前描述符不可用??
  121.   ????????????????????{??
  122.   ???????????????????????close(sockfd);??
  123.   ???????????????????????client[i].fd?=?-1;??
  124.   ????????????????????}??
  125.   ????????????????????else??
  126.   ????????????????????????perror("read?error");??
  127.   ????????????????}??
  128.  ???????????????else?if(n?==?0)?//如果數據讀取完畢,關閉連接,設置當前描述符不可用??
  129.   ????????????????{??
  130.   ????????????????????close(sockfd);??
  131.   ????????????????????client[i].fd?=?-1;??
  132.   ????????????????}??
  133.   ????????????????else??
  134.   ????????????????????write(sockfd,?buf,?n);?//打印數據??
  135.   ?????????????if(--nready?<=?0)??
  136.   ?????????????????break;??
  137.   ????????????}??
  138.   ????????}??
  139.   ???}??
  140.   ???exit(0);??
  141.  }??
賜教!

本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。
如若轉載,請注明出處:http://www.pswp.cn/news/384098.shtml
繁體地址,請注明出處:http://hk.pswp.cn/news/384098.shtml
英文地址,請注明出處:http://en.pswp.cn/news/384098.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

鏈表相關筆試面試題

1.判斷兩個鏈表是否相交 兩個鏈表是否相交可分為以下幾種情況 ????&#xff08;1&#xff09;兩個鏈表都不帶環&#xff0c;此時兩個鏈表所對應的最后一個節點是相等的 ????&#xff08;2&#xff09;兩個鏈表一個帶環&#xff0c;一個不帶環&#xff0c;兩個鏈表一定…

Linux經典問題—五哲學家就餐問題

http://m.blog.csdn.net/aspenstars/article/details/70149038 一、問題介紹 由Dijkstra提出并解決的哲學家進餐問題(The Dinning Philosophers Problem)是典型的同步問題。該問題是描述有五個哲學家共用一張圓桌&#xff0c;分別坐在周圍的五張椅子上&#xff0c;在圓桌上有五…

修改之前的myshell使之支持輸入輸出重定向

1.open函數 ????這個函數是打開一個文件&#xff08;文件名叫pathname),以 flag 權限打開&#xff0c;flag 包括了以下幾種 O_RDONLY&#xff08;只讀&#xff09;, O_WRONLY&#xff08;只寫&#xff09;, O_RDWR&#xff08;讀寫&#xff09;&#xff0c;當文件打開成…

HDU - 6621 K-th Closest Distance——主席樹+二分

【題目描述】 HDU - 6621 K-th Closest Distance 【題目分析】 因為看到第kkk大的要求&#xff0c;剛開始的時候一直都在想怎么運用第kkk大來解決問題&#xff0c;但是后來看其他人的博客才發現并不需要用第k大&#xff0c;但是主席樹維護權值線段樹還是需要的&#xff0c;這…

鏈表相關的算法題大匯總 — 數據結構之鏈表奇思妙想

http://blog.csdn.net/lanxuezaipiao/article/details/22100021基本函數&#xff08;具體代碼實現見后面&#xff09; 1&#xff0c;構造節點 //定義節點類型 struct Node { int value; Node*next; }; 2&#xff0c;分配節點 //之所以要分配節點原因是需要在分配函數中…

CodeForces - 372CWatching Fireworks is Fun+DP+單調隊列優化

【題目描述】 CodeForces - 372CWatching Fireworks is Fun 題目的大概意思就是在一個編號為1…n的街道上現在按照時間順序放煙花&#xff0c;每個煙花獲得的幸福感為b?abs(a?x)b-abs(a-x)b?abs(a?x)&#xff0c;x為觀看煙花的位置&#xff0c;為了提升我們的幸福感&#x…

雙向鏈表的基本操作

1.雙向鏈表的數據結構 typedef char DLinkType;typedef struct DLinkNode { DLinkType data; struct DLinkNode* next; struct DLinkNode* prev; }DLinkNode; 雙向帶頭結點的鏈表有三個成員&#xff0c; 一個是數據&#xff0c; 一個是指針 next 指向當前結點的下一個結點&…

匿名管道

1.進程通信的目的 (1) 數據傳輸: 一個進程需要將它的數據傳輸給另一個進程 ????(2) 資源共享: 多個進程之間共享同樣的資源 ????(3) 通知事件: 一個進程需要向另一個或一組進程發送消息, 通知它們發生了什么事情 2.管道 管道是一種進程之間通信的一種方式, 我們把從…

Currency Exchange——最短路Bellman-Ford算法

【題目描述】 Several currency exchange points are working in our city. Let us suppose that each point specializes in two particular currencies and performs exchange operations only with these currencies. There can be several points specializing in the sam…

C++實現String類

http://blog.csdn.net/randyjiawenjie/article/details/6709539 C實現String類&#xff0c;還沒有完成&#xff0c;待繼續。 有以下注意的點&#xff1a; &#xff08;1&#xff09;賦值操作符返回的是一個MyString&&#xff0c;而重載的返回的是一個MyString。其中的原因…

POJ 3370 Halloween treats——鴿巢原理+思維

【題目描述】 POJ 3370 Halloween treats Description Every year there is the same problem at Halloween: Each neighbour is only willing to give a certain total number of sweets on that day, no matter how many children call on him, so it may happen that a chi…

將信號量代碼生成靜態庫以及動態庫

1.信號量相關代碼生成靜態庫 2.信號量相關代碼生成動態庫

Wormholes——Bellman-Ford判斷負環

【題目描述】 While exploring his many farms, Farmer John has discovered a number of amazing wormholes. A wormhole is very peculiar because it is a one-way path that delivers you to its destination at a time that is BEFORE you entered the wormhole! Each of…

C++11 標準新特性:Defaulted 和 Deleted 函數

https://www.ibm.com/developerworks/cn/aix/library/1212_lufang_c11new/index.html Defaulted 函數 背景問題 C 的類有四類特殊成員函數&#xff0c;它們分別是&#xff1a;默認構造函數、析構函數、拷貝構造函數以及拷貝賦值運算符。這些類的特殊成員函數負責創建、初始化、…

順序表實現棧相關操作

1.棧的相關概念 棧是一種特殊的線性表, 其中只允許在固定的一端進行插入和刪除元素.進行數據插入和刪除的一端叫做棧頂, 另一端成為棧底. 不含任何元素的棧稱為空棧, 棧又稱為先進先出的線性表. 2. 順序棧的結構 3. 順序棧的具體操作 (1). 數據結構 typedef char SeqStackTyp…

MPI Maelstrom——Dijkstra

【題目描述】 BIT has recently taken delivery of their new supercomputer, a 32 processor Apollo Odyssey distributed shared memory machine with a hierarchical communication subsystem. Valentine McKee’s research advisor, Jack Swigert, has asked her to bench…

雙向帶環帶頭結點的鏈表實現棧

1. 數據結構 利用帶頭結點帶環的結點實現棧的相關操作.因此, 每一個結點包括了一個前驅, 一個后繼, 還有一個數據成員 typedef char DLinkStackType;typedef struct DLinkStack {DLinkStackType data;struct DLinkStack* next;struct DLinkStack* prev; }DLinkStack;2. 初始化…

Cow Contest——Floyed+連通性判斷

【題目描述】 N (1 ≤ N ≤ 100) cows, conveniently numbered 1…N, are participating in a programming contest. As we all know, some cows code better than others. Each cow has a certain constant skill rating that is unique among the competitors. The contest …

C++11 標準新特性:委派構造函數

https://www.ibm.com/developerworks/cn/rational/1508_chenjing_c11/index.html陳 晶2015 年 8 月 11 日發布WeiboGoogle用電子郵件發送本頁面 1本文首先介紹了在委派構造函數提出之前類成員構造所面臨的問題&#xff0c;再結合實例介紹了委派構造函數的用法&#xff0c;并說明…

順序表實現隊列

一. 隊列相關概念 隊列是只允許在一段進行插入元素, 在另一端進行刪除元素的線性表,即只允許對隊列進行尾插,頭刪的操作.隊列具有先進先出, 后進后出的特性. ???????? 1.初始化 void SeqQueInit(SeqQue* q) {if(q NULL){return;//非法輸入}q -> head 0;q -> …