使用poll實現的io多路復用服務端和客戶端

http://blog.csdn.net/robertkun/article/details/52269313

參考:http://www.cnblogs.com/Anker/p/3261006.html


使用poll實現的io多路復用服務端和客戶端。

客戶端通過子進程創建多個客戶端連接。

客戶端每隔1秒向服務端發送一個時間戳,

服務端接收到時間戳以后,保存在本地的文件中,

一個客戶端對應一個存儲文件,

并將接收到的時間戳返回給客戶端。


代碼:

服務端:

[cpp]?view plaincopy
  1. #include?<stdio.h>??
  2. #include?<stdlib.h>??
  3. #include?<string.h>??
  4. #include?<fcntl.h>??
  5. #include?<poll.h>??
  6. #include?<errno.h>??
  7. #include?<unistd.h>??
  8. ??
  9. #include?<sys/ioctl.h>??
  10. #include?<sys/types.h>??
  11. #include?<sys/socket.h>??
  12. #include?<sys/stat.h>??
  13. ??
  14. #include?<netinet/in.h>??
  15. #include?<arpa/inet.h>??
  16. ??
  17. ??
  18. #define?IP_ADDR?????"127.0.0.1"??
  19. #define?PORT????????59999??
  20. #define?LISTEN_Q????5??
  21. #define?OPEN_MAX????100000??
  22. #define?INFTIM??????-1??
  23. #define?MAX_LINE????1024??
  24. ??
  25. static?int?socket_bind(const?char*?ip,?int?port);??
  26. static?void?do_poll(int?ln_fd);??
  27. static?void?handle_conn(struct?pollfd*?conn_fds,?int?num,?int*?files);??
  28. ??
  29. int?main()??
  30. {??
  31. ????int?ln_fd,?cn_fd,?sk_fd?=?0;??
  32. ????struct?sockaddr_in?_addr;??
  33. ??
  34. ????socklen_t?_len;??
  35. ????ln_fd?=?socket_bind(IP_ADDR,?PORT);??
  36. ????listen(ln_fd,?LISTEN_Q);??
  37. ??
  38. ????do_poll(ln_fd);??
  39. ????return?0;??
  40. }??
  41. ??
  42. ??
  43. static?int?socket_bind(const?char*?ip,?int?port)??
  44. {??
  45. ????int?ln_fd;??
  46. ????struct?sockaddr_in?_addr;??
  47. ????ln_fd?=?socket(AF_INET,?SOCK_STREAM,?0);??
  48. ????if(ln_fd?==?-1)?{??
  49. ????????perror("socket?error!");??
  50. ????????exit(1);??????????
  51. ????}??
  52. ??
  53. ????bzero(&_addr,?sizeof(_addr));??
  54. ????_addr.sin_family?=?AF_INET;??
  55. ????inet_pton(AF_INET,?ip,?&_addr.sin_addr);??
  56. ????_addr.sin_port?=?htons(port);??
  57. ??
  58. ????if(bind(ln_fd,?(struct?sockaddr*)&_addr,?sizeof(_addr))?==?-1)?{??
  59. ????????perror("bind?error!");??
  60. ????????exit(1);??
  61. ????}??
  62. ??
  63. ????return?ln_fd;??
  64. }??
  65. ??
  66. static?void?do_poll(int?ln_fd)??
  67. {??
  68. ????int?connfd,?sockfd?=?0;??
  69. ????struct?sockaddr_in?_addr;??
  70. ????socklen_t?_len;??
  71. ????int?files[OPEN_MAX];??
  72. ????struct?pollfd?clients[OPEN_MAX];??
  73. ????int?nMax,?i,?nReady?=?0;??
  74. ??????
  75. ????clients[0].fd?=?ln_fd;??
  76. ????clients[0].events?=?POLLIN;??
  77. ??????
  78. ????for(i?=?1;?i<OPEN_MAX;?++i)?{??
  79. ????????clients[i].fd?=?-1;??
  80. ????}??
  81. ????nMax?=?0;??
  82. ??
  83. ????while(1)?{??
  84. ????????nReady?=?poll(clients,?nMax+1,?INFTIM);??
  85. ????????if(nReady?==?-1)?{??
  86. ????????????perror("poll?error!");??
  87. ????????????exit(1);??
  88. ????????}??
  89. ????????else?{??
  90. ????????????printf("poll?ready?num?=?%d\n",?nReady);??
  91. ????????}??
  92. ??
  93. ????????if(clients[0].revents?&?POLLIN)?{??
  94. ????????????_len?=?sizeof(_addr);??
  95. ????????????if((connfd?=?accept(ln_fd,?(struct?sockaddr*)&_addr,?&_len))?==?-1)?{??
  96. ????????????????if(errno?==?EINTR)?{??
  97. ????????????????????printf("EINTR!\n");??
  98. ????????????????????continue;??
  99. ????????????????}??
  100. ????????????????else?{??
  101. ????????????????????perror("accept?error!");??
  102. ????????????????????exit(1);??
  103. ????????????????}??
  104. ????????????}??
  105. ??
  106. ????????????fprintf(stdout,?"accept?a?new?client!?[%s]\n",?inet_ntoa(_addr.sin_addr));??
  107. ??
  108. ????????????for(i=1;?i<OPEN_MAX;?++i)?{??
  109. ????????????????if(clients[i].fd?<?0)?{??
  110. ????????????????????fcntl(connfd,?F_SETFL,?fcntl(connfd,F_GETFL)|?O_NONBLOCK);??
  111. ????????????????????unsigned?long?nVal=1;??
  112. ????????????????????ioctl(connfd,?FIONBIO,?&nVal);??
  113. ??
  114. ????????????????????clients[i].fd?=?connfd;??
  115. ????????????????????char?path[2048]?=?{"\0"};??
  116. ????????????????????getcwd(path,?sizeof(path));??
  117. ??????????????????????
  118. ????????????????????sprintf(path,?"%s/tmp_%d.txt",?path,?i);??
  119. ????????????????????printf("path=%s\n",?path);??
  120. ????????????????????int?fd?=?open(path,?O_RDWR|O_APPEND|O_CREAT,?0666);??
  121. ????????????????????if(fd?>?0)?{??
  122. ????????????????????????files[i]?=?fd;??
  123. ????????????????????}??
  124. ????????????????????else?{??
  125. ????????????????????????fprintf(stdout,?"open?file?error!?[%s]\n",?path);??
  126. ????????????????????????perror("open?file?error!");??
  127. ????????????????????}??
  128. ??
  129. ????????????????????break;??
  130. ????????????????}??
  131. ????????????}??
  132. ??
  133. ????????????fflush(stdout);??
  134. ??
  135. ????????????if(i?==?OPEN_MAX)?{??
  136. ????????????????fprintf(stderr,?"too?many?clients\n");??
  137. ????????????????exit(1);??
  138. ????????????}??
  139. ??
  140. ????????????clients[i].events?=?POLLIN;??
  141. ????????????nMax?=?(i?>?nMax???i?:?nMax);??
  142. ????????????if(--nReady?<=?0)?{??
  143. ????????????????printf("nReady?=?%d,?nMax?=?%d\n",?nReady,?nMax);??
  144. ????????????????continue;??
  145. ????????????}??
  146. ????????}??
  147. ??????????
  148. ????????handle_conn(clients,?nMax,?files);??
  149. ????}??
  150. }??
  151. ??
  152. static?void?handle_conn(struct?pollfd*?conn_fds,?int?num,?int*?files)??
  153. {??
  154. ????int?i,?n?=?0;??
  155. ????char?buf[MAX_LINE];??
  156. ????memset(buf,?0,?MAX_LINE);??
  157. ????for(i=1;?i<=num;?++i)??
  158. ????{??
  159. ????????if(conn_fds[i].fd?<?0)??
  160. ????????????continue;??
  161. ??
  162. ????????if(conn_fds[i].revents?&?POLLIN)?{??
  163. ????????????n?=?read(conn_fds[i].fd,?buf,?MAX_LINE);??
  164. ????????????if(n?==?0)?{??
  165. ????????????????close(conn_fds[i].fd);??
  166. ????????????????conn_fds[i].fd?=?-1;??
  167. ????????????????continue;??
  168. ????????????}??
  169. ??
  170. ????????????write(files[i],?buf,?n);??
  171. ????????????write(conn_fds[i].fd,?buf,?n);??
  172. ????????}??
  173. ????}??
  174. }??

客戶端:

[cpp]?view plaincopy
  1. #include?<stdio.h>??
  2. #include?<stdlib.h>??
  3. #include?<string.h>??
  4. ??
  5. #include?<unistd.h>??
  6. #include?<sys/types.h>??
  7. #include?<sys/socket.h>??
  8. ??
  9. #include?<netinet/in.h>??
  10. #include?<poll.h>??
  11. #include?<errno.h>??
  12. #include?<arpa/inet.h>??
  13. ??
  14. #define?MAX_LINE????1024??
  15. #define?IP_ADDR?????"127.0.0.1"??
  16. #define?SERV_PORT???59999??
  17. ??
  18. #define?max(a,b)?(a>b)?a:b??
  19. ??
  20. static?void?do_conn();??
  21. static?void?handle_conn(int?sockfd);??
  22. ??
  23. int?main(int?args,?char*?argv[])??
  24. {??
  25. ????int?i?=?0;??
  26. ????for(i=0;?i<2000;?++i)?{??
  27. ????????pid_t?fpid?=?-1;??
  28. ????????fpid?=?fork();??
  29. ????????if(fpid?<?0)?{??
  30. ????????????printf("error?in?fork!");??
  31. ????????}??
  32. ????????else?if(fpid?==?0)?{??
  33. ????????????do_conn();??
  34. ????????}??
  35. ????????else?{??
  36. ????????????//do_conn();??
  37. ????????}??
  38. ????}??
  39. ??
  40. ????return?0;??
  41. }??
  42. ??
  43. static?void?do_conn()??
  44. {??
  45. ????int?sockfd;??
  46. ????struct?sockaddr_in?_addr;??
  47. ????sockfd?=?socket(AF_INET,?SOCK_STREAM,?0);??
  48. ??
  49. ????bzero(&_addr,?sizeof(_addr));??
  50. ????_addr.sin_family?=?AF_INET;??
  51. ????_addr.sin_port?=?htons(SERV_PORT);??
  52. ??
  53. ????inet_pton(AF_INET,?IP_ADDR,?&_addr.sin_addr);??
  54. ????int?ret?=?connect(sockfd,?(struct?sockaddr*)&_addr,?sizeof(_addr));??
  55. ????if(ret?<?0)?{??
  56. ????????perror("connect?failed!");??
  57. ????????exit(1);??
  58. ????}??
  59. ??
  60. ????handle_conn(sockfd);??
  61. }??
  62. ??
  63. static?void?handle_conn(int?sockfd)??
  64. {??
  65. ????char?send_line[MAX_LINE]?=?{'\0'};??
  66. ????char?recv_line[MAX_LINE]?=?{'\0'};??
  67. ??
  68. ????struct?pollfd?pfds[1];??
  69. ????pfds[0].fd?=?sockfd;??
  70. ????pfds[0].events?=?POLLIN|POLLOUT;??
  71. ??
  72. ????while(1)?{??
  73. ????????poll(pfds,?1,?1000);??
  74. ????????if(pfds[0].revents?&?POLLIN)?{??
  75. ????????????int?ret?=?read(sockfd,?recv_line,?MAX_LINE);??
  76. ????????????if(ret?==?0)?{??
  77. ????????????????perror("client:?server?is?closed.");??
  78. ????????????????close(sockfd);??
  79. ????????????????continue;??
  80. ????????????}??
  81. ????????????else?if(ret?<?0)?{??
  82. ????????????????perror("client:?read?error!");??
  83. ????????????????continue;??
  84. ????????????}??
  85. ??
  86. ????????????//printf("[%d]?recv=%s\n",?(int)getpid(),?recv_line);??
  87. ????????}??
  88. ??
  89. ????????if(pfds[0].revents?&?POLLOUT)?{??
  90. ????????????time_t?_time?=?time(0);??
  91. ????????????char?dt[20]={"\0"};??
  92. ????????????sprintf(dt,?"%d\n",?_time);??
  93. ??
  94. ????????????memcpy(send_line,?dt,?strlen(dt));??
  95. ????????????int?ret?=?write(sockfd,?send_line,?strlen(send_line));??
  96. ????????????if(ret?<?0)?{??
  97. ????????????????perror("write?error!!");??
  98. ????????????}??
  99. ????????}??
  100. ??
  101. ????????sleep(1);??
  102. ????}??
  103. ??
  104. ????shutdown(sockfd,?SHUT_WR);??
  105. }??

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

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

相關文章

【Java學習筆記三】抽象類與接口

對象的類型轉換分為自動轉換和強制轉換兩種 派生類向基類轉換是自動轉換&#xff0c;因為派生類中包含基類基類向派生類的轉換是強制轉換 強制類型轉換是通過在轉換對象前面使用圓括號運算符來實現&#xff0c;圓括號內為要轉換的目標類型&#xff0c;格式為&#xff1a; (&…

Epoll 的tcp通信代碼(服務器+客戶端)

http://blog.csdn.net/libinbin_1014/article/details/50096187 Epoll 的tcp通信代碼&#xff08;服務器客戶端&#xff09; /* gcc -D_LARGEFILE64_SOURCE -D_FILE_OFFSET_BITS64 -I${ORACLE_HOME}/rdbms/public -I${ORACLE_HOME}/rdbms/demo -L${ORACLE_HOME}/lib -lclntsh …

【Java學習筆記四】Java中的包

包的聲明和引入&#xff1a;在Java語言系統中&#xff0c;Java編譯器為每一個類生成一個字節碼文件&#xff08;.class&#xff09;&#xff0c;為了對類文件進行分層和按用途分類管理&#xff0c;同時也為了解決相同類名的文件沖突的問題&#xff0c;Java提供了包機制來管理類…

Linux系統編程——線程池

http://blog.csdn.net/tennysonsky/article/details/46490099# 線程池基本原理 在傳統服務器結構中&#xff0c;常是有一個總的監聽線程監聽有沒有新的用戶連接服務器&#xff0c;每當有一個新的用戶進入&#xff0c;服務器就開啟一個新的線程用戶處理這 個用戶的數據包。這個線…

【Java學習筆記五】Java異常處理

異常通常分為三類&#xff1a; 程序可控制的異常&#xff1a;一般是可預見的錯誤&#xff0c;不是致命的。例如&#xff1a;除數為0&#xff0c;數組下標越界。程序不可控制的的異常&#xff1a;這種異常往往是致命的&#xff0c;但是系統可以預見的。例如&#xff1a;系統棧溢…

【C++學習筆記一】C++類和對象詳解

類定義是以關鍵字class開頭&#xff0c;后面跟類的名稱。主體是包含在一對花括號中。類定義后必須跟著一個分號或一個聲明列表。 類的對象的公共數據成員可以使用直接成員訪問運算符.來訪問。需要注意的是&#xff0c;私有的成員和受保護的成員不能直接使用成員訪問運算符來訪…

C語言實現的簡單的線程池

http://www.linuxidc.com/Linux/2013-01/77619.htm 有時我們會需要大量線程來處理一些相互獨立的任務&#xff0c;為了避免頻繁的申請釋放線程所帶來的開銷&#xff0c;我們可以使用線程池。下面是一個C語言實現的簡單的線程池。 頭文件&#xff1a; 1: #ifndef THREAD_POOL_H_…

C++獲取當前時間

可以使用windowsAPI直接獲取。 例如&#xff1a; #include<windows.h> #include<cstdio>using namespace std;int main() {SYSTEMTIME now;GetLocalTime(&now);printf("現在是%02d時%02d分%02d秒\n",now.wHour,now.wMinute,now.wSecond);printf(&…

成員函數后面加上const的作用

const表示成員函數不會修改類中的數據成員。 規則&#xff1a; 在類中被const 聲明的函數只能訪問const 函數&#xff0c;而非const 函數可以訪問任意成員函數。在成員函數中不管數據是否具有const 屬性&#xff0c;編譯器檢查的的是是否有修改&#xff08;賦值&#xff0c;自…

簡單Linux C線程池

http://www.cnblogs.com/venow/archive/2012/11/22/2779667.html 大多數的網絡服務器&#xff0c;包括Web服務器都具有一個特點&#xff0c;就是單位時間內必須處理數目巨大的連接請求&#xff0c;但是處理時間卻是比較短的。在傳統的多線程服務器模型中是這樣實現的&#xff1…

C++創建對象:棧和堆的區別

首先我們應該了解棧和堆的差別&#xff1a; 詳細信息&#xff1a;傳送門 棧相當于函數自帶的存儲空間&#xff0c;在windows下一般為2M,在Linux下一般為8M&#xff0c;存取速度稍微快一點。堆是系統的空間&#xff0c;相對較大&#xff0c;一般為2G&#xff0c;效率稍微慢一點…

IO多路復用之poll總結

http://www.cnblogs.com/Anker/p/3261006.html 1、基本知識 poll的機制與select類似&#xff0c;與select在本質上沒有多大差別&#xff0c;管理多個描述符也是進行輪詢&#xff0c;根據描述符的狀態進行處理&#xff0c;但是poll沒有最大文件描述符數量的限制。poll和select同…

【C++學習筆記二】C++繼承

繼承 繼承允許我們一句另一個類來定義一個類&#xff0c;這使得繼承和維護一個程序變得更加容易&#xff0c;也達到了重用代碼功能和提高執行效率的效果。 一般格式為&#xff1a; class 派生類名 :訪問修飾符 基類名{};其中訪問修飾符是public protected private中的一個&a…

處理大并發之二 對epoll的理解,epoll客戶端服務端代碼

http://blog.csdn.net/wzjking0929/article/details/51838370 序言&#xff1a; 該博客是一系列的博客&#xff0c;首先從最基礎的epoll說起&#xff0c;然后研究libevent源碼及使用方法&#xff0c;最后研究nginx和node.js&#xff0c;關于select,poll這里不做說明&#xff0c…

C++基類指針指向派生類(指針)

我們常用基類指針指向派生類對象來實現多態性。 私有繼承不允許基類指針指向派生類 基類指針只能訪問到基類中含有的公有成員。 當用基類指針指向派生類對象在動態分配堆上內存的時候&#xff0c;析構函數必須是虛函數! 成員如果是數據成員的話訪問的是基類的版本&#xff…

C++虛繼承中構造函數和析構函數順序問題以及原理

多重繼承的問題&#xff1a;多個類B,C,…繼承同一個類A導致如果X繼承了B,C,…那么在X中將還有多個A中成員的拷貝&#xff0c;如果想要訪問A中的成員如果不加名字空間將會導致二義性&#xff0c;這種拷貝大多是沒有實際意義的&#xff0c;為了避免這種空間浪費&#xff0c;C有虛…

一個簡單的linux線程池

http://blog.csdn.net/wzjking0929/article/details/20312675 線程池&#xff1a;簡單地說&#xff0c;線程池 就是預先創建好一批線程&#xff0c;方便、快速地處理收到的業務。比起傳統的到來一個任務&#xff0c;即時創建一個線程來處理&#xff0c;節省了線程的創建和回收的…

【C++學習筆記三】C++多態、抽象(接口)

當類之間存在多種層次結構&#xff0c;并且類之間通過繼承關聯時就會用到多態。 虛函數在子類中的覆蓋版本和該函數在基類中的原始版本必須有相同的函數簽名、函數名、形參名、常屬性。如果返回值為非類類型&#xff0c;則必須相同&#xff0c;如果是類類型A的指針或者引用&am…

C++重載和重寫的條件以及重寫后對基類函數的覆蓋

重載&#xff1a;同一個類中名字相同&#xff0c;參數列表不同的方法構成重載函數&#xff0c;和返回值沒有關系。這就意味著就算返回值不同&#xff0c;只要名字相同參數列表相同編譯器還是會報錯&#xff0c;覺得一函數被定義了兩次。 重寫&#xff1a;派生類中只要函數名字…

C++靜態成員和靜態方法

在類中&#xff0c;靜態成員可以實現多個對象之間共享數據&#xff0c;同時保證了安全性。靜態數據對該類的所有對象是公有的&#xff0c;存儲一處供所有對象使用。 注意&#xff1a; 靜態成員定義時需要在前面加上關鍵字static靜態成員必須初始化且必須在類外進行&#xff0…