Linux網絡編程——tcp并發服務器(I/O復用之select

http://blog.csdn.net/lianghe_work/article/details/46519633

多線程、多進程相比,I/O復用最大的優勢是系統開銷小,系統不需要建立新的進程或者線程,也不必維護這些線程和進程。


代碼示例:

[csharp]?view plain?copy
  1. #include?<stdio.h>???
  2. #include?<unistd.h>??
  3. #include?<stdlib.h>??
  4. #include?<errno.h>??
  5. #include?<string.h>??
  6. #include?<sys/socket.h>??
  7. #include?<sys/types.h>??
  8. #include?<netinet/in.h>??
  9. #include?<arpa/inet.h>??
  10. #include?<sys/select.h>??
  11. ?
  12. #define?SERV_PORT?8080??
  13. #define?LIST?20????????????????//服務器最大接受連接??
  14. #define?MAX_FD?10??????????????//FD_SET支持描述符數量??
  15. ??
  16. ??
  17. int?main(int?argc,?char?*argv[])??
  18. {??
  19. ????int?sockfd;??
  20. ????int?err;??
  21. ????int?i;??
  22. ????int?connfd;??
  23. ????int?fd_all[MAX_FD];?//保存所有描述符,用于select調用后,判斷哪個可讀??
  24. ??????
  25. ????//下面兩個備份原因是select調用后,會發生變化,再次調用select前,需要重新賦值??
  26. ????fd_set?fd_read;????//FD_SET數據備份??
  27. ????fd_set?fd_select;??//用于select??
  28. ??
  29. ????struct?timeval?timeout;?????????//超時時間備份??
  30. ????struct?timeval?timeout_select;??//用于select??
  31. ??????
  32. ????struct?sockaddr_in?serv_addr;???//服務器地址??
  33. ????struct?sockaddr_in?cli_addr;????//客戶端地址??
  34. ????socklen_t?serv_len;??
  35. ????socklen_t?cli_len;??
  36. ??????
  37. ????//超時時間設置??
  38. ????timeout.tv_sec?=?10;??
  39. ????timeout.tv_usec?=?0;??
  40. ??????
  41. ????//創建TCP套接字??
  42. ????sockfd?=?socket(AF_INET,?SOCK_STREAM,?0);??
  43. ????if(sockfd?<?0)??
  44. ????{??
  45. ????????perror("fail?to?socket");??
  46. ????????exit(1);??
  47. ????}??
  48. ??????
  49. ????//?配置本地地址??
  50. ????memset(&serv_addr,?0,?sizeof(serv_addr));??
  51. ????serv_addr.sin_family?=?AF_INET;?????????//?ipv4??
  52. ????serv_addr.sin_port?=?htons(SERV_PORT);??//?端口,?8080??
  53. ????serv_addr.sin_addr.s_addr?=?htonl(INADDR_ANY);?//?ip??
  54. ??
  55. ????serv_len?=?sizeof(serv_addr);??
  56. ??????
  57. ????//?綁定??
  58. ????err?=?bind(sockfd,?(struct?sockaddr?*)&serv_addr,?serv_len);??
  59. ????if(err?<?0)??
  60. ????{??
  61. ????????perror("fail?to?bind");??
  62. ????????exit(1);??
  63. ????}??
  64. ??
  65. ????//?監聽??
  66. ????err?=?listen(sockfd,?LIST);??
  67. ????if(err?<?0)??
  68. ????{??
  69. ????????perror("fail?to?listen");??
  70. ????????exit(1);??
  71. ????}??
  72. ??????
  73. ????//初始化fd_all數組??
  74. ????memset(fd_all,?-1,?sizeof(fd_all));??
  75. ??
  76. ????fd_all[0]?=?sockfd;???//第一個為監聽套接字??
  77. ??????
  78. ????FD_ZERO(&fd_read);??//?清空??
  79. ????FD_SET(sockfd,?&fd_read);??//將監聽套接字加入fd_read??
  80. ??
  81. ????int?maxfd?=?fd_all[0];??//監聽的最大套接字??
  82. ??????
  83. ????while(1){??
  84. ??????
  85. ????????//?每次都需要重新賦值,fd_select,timeout_select每次都會變??
  86. ????????fd_select?=?fd_read;??
  87. ????????timeout_select?=?timeout;??
  88. ??????????
  89. ????????//?檢測監聽套接字是否可讀,沒有可讀,此函數會阻塞??
  90. ????????//?只要有客戶連接,或斷開連接,select()都會往下執行??
  91. ????????err?=?select(maxfd+1,?&fd_select,?NULL,?NULL,?NULL);??
  92. ????????//err?=?select(maxfd+1,?&fd_select,?NULL,?NULL,?(struct?timeval?*)&timeout_select);??
  93. ????????if(err?<?0)??
  94. ????????{??
  95. ????????????????perror("fail?to?select");??
  96. ????????????????exit(1);??
  97. ????????}??
  98. ??
  99. ????????if(err?==?0){??
  100. ????????????printf("timeout\n");??
  101. ????????}??
  102. ??????????
  103. ????????//?檢測監聽套接字是否可讀??
  104. ????????if(?FD_ISSET(sockfd,?&fd_select)?){//可讀,證明有新客戶端連接服務器??
  105. ??????????????
  106. ????????????cli_len?=?sizeof(cli_addr);??
  107. ??????????????
  108. ????????????//?取出已經完成的連接??
  109. ????????????connfd?=?accept(sockfd,?(struct?sockaddr?*)&cli_addr,?&cli_len);??
  110. ????????????if(connfd?<?0)??
  111. ????????????{??
  112. ????????????????perror("fail?to?accept");??
  113. ????????????????exit(1);??
  114. ????????????}??
  115. ??????????????
  116. ????????????//?打印客戶端的?ip?和端口??
  117. ????????????char?cli_ip[INET_ADDRSTRLEN]?=?{0};??
  118. ????????????inet_ntop(AF_INET,?&cli_addr.sin_addr,?cli_ip,?INET_ADDRSTRLEN);??
  119. ????????????printf("----------------------------------------------\n");??
  120. ????????????printf("client?ip=%s,port=%d\n",?cli_ip,ntohs(cli_addr.sin_port));??
  121. ??????????????
  122. ????????????//?將新連接套接字加入?fd_all?及?fd_read??
  123. ????????????for(i=0;?i?<?MAX_FD;?i++){??
  124. ????????????????if(fd_all[i]?!=?-1){??
  125. ????????????????????continue;??
  126. ????????????????}else{??
  127. ????????????????????fd_all[i]?=?connfd;??
  128. ????????????????????printf("client?fd_all[%d]?join\n",?i);??
  129. ????????????????????break;??
  130. ????????????????}??
  131. ????????????}??
  132. ??????????????
  133. ????????????FD_SET(connfd,?&fd_read);??
  134. ??????????????
  135. ????????????if(maxfd?<?connfd)??
  136. ????????????{??
  137. ????????????????maxfd?=?connfd;??//更新maxfd??
  138. ????????????}??
  139. ??????????
  140. ????????}??
  141. ??????????
  142. ????????//從1開始查看連接套接字是否可讀,因為上面已經處理過0(sockfd)??
  143. ????????for(i=1;?i?<?maxfd;?i++){??
  144. ????????????if(FD_ISSET(fd_all[i],?&fd_select)){??
  145. ????????????????printf("fd_all[%d]?is?ok\n",?i);??
  146. ??????????????????
  147. ????????????????char?buf[1024]={0};??//讀寫緩沖區??
  148. ????????????????int?num?=?read(fd_all[i],?buf,?1024);??
  149. ????????????????if(num?>?0){??
  150. ??
  151. ????????????????????//收到?客戶端數據并打印??
  152. ????????????????????printf("receive?buf?from?client?fd_all[%d]?is:?%s\n",?i,?buf);??
  153. ??????????????????????
  154. ????????????????????//回復客戶端??
  155. ????????????????????num?=?write(fd_all[i],?buf,?num);??
  156. ????????????????????if(num?<?0){??
  157. ????????????????????????perror("fail?to?write?");??
  158. ????????????????????????exit(1);??
  159. ????????????????????}else{??
  160. ????????????????????????//printf("send?reply\n");??
  161. ????????????????????}??
  162. ??????????????????????
  163. ????????????????}??
  164. ????????????????else?if(0?==?num){?//?客戶端斷開時??
  165. ??????????????????????
  166. ????????????????????//客戶端退出,關閉套接字,并從監聽集合清除??
  167. ????????????????????printf("client:fd_all[%d]?exit\n",?i);??
  168. ????????????????????FD_CLR(fd_all[i],?&fd_read);??
  169. ????????????????????close(fd_all[i]);??
  170. ????????????????????fd_all[i]?=?-1;??
  171. ??????????????????????
  172. ????????????????????continue;??
  173. ????????????????}??
  174. ??????????????????
  175. ????????????}else?{??
  176. ????????????????//printf("no?data\n");????????????????????
  177. ????????????}??
  178. ????????}??
  179. ????}??
  180. ??????
  181. ????return?0;??
  182. }??

運行結果:


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

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

相關文章

ets

:ets.new(table_name, pattern) 第一個參數是表名&#xff0c;第二個參數是表的設置選項。 :set  一個key&#xff0c;一個數據&#xff0c;無序 :ordered_set  一個key&#xff0c;一個數據&#xff0c;有序&#xff1b; 1 1.0 :bag  一個key&#xff0c;多個數據&…

貪心算法-區間選點問題-種樹

【題目描述】一條街道的一邊有幾座房子。因為環保原因居民想要在路邊種些樹&#xff0c;路邊的地區被分割成n塊&#xff0c;并被編號為1~n。每塊大小為一個單位尺寸且最多可總一棵樹。每個居民想在門前種些樹并制定了三個數b,e,t&#xff0c;這三個數代表居民想在b和e之間最少種…

ets注意事項

當表類型為 :set 時&#xff0c;使用 :ets.first 和 :ets.last 會獲取到同一個 key。將表類型換為 :oedered_set 就可以避免這種情況 轉載于:https://www.cnblogs.com/lr1402585172/p/11599219.html

CodeForces - 1141CPolycarp Restores Permutation搜索+剪枝

Polycarp Restores Permutation 【題意分析】題意大概是給定一個串&#xff0c;包含從1到n所有的數字。但是給定的是相鄰數字的差&#xff0c;需要復原這個串。 大概分析以后發現給定的是一個差分數組&#xff0c;所以只需要枚舉第一個元素就可以確定所有元素的值。 問題是如何…

CodeForces - 1141ESuperhero Battle簡單模擬

Superhero Battle 這道題卡了我一個多小時&#xff0c;最后也沒有做出來&#xff0c;成功稱為吊車尾。。。 思路什么的都沒有問題&#xff0c;主要是&#xff0c;爆long long了&#xff0c;這個太可怕了&#xff0c;就因為一個中間變量忘記開longlong導致一直一直wa&#xff0c…

Linux下的I/O復用與epoll詳解

http://www.cnblogs.com/lojunren/p/3856290.html 前言 I/O多路復用有很多種實現。在linux上&#xff0c;2.4內核前主要是select和poll&#xff0c;自Linux 2.6內核正式引入epoll以來&#xff0c;epoll已經成為了目前實現高性能網絡服務器的必備技術。盡管他們的使用方法不盡相…

校門外的樹——樹狀數組+區間修改

校門外的樹 【題目分析】題目描述的是一種區間修改&#xff0c;看起來好像要用線段樹。但是對于這種區間內部沒有差別并且查詢的是區間內的類別的問題&#xff0c;是可以轉化為樹狀數組進行的。畢竟樹狀數組更加簡單。 我們的關注點應該放在區間的端點處&#xff0c;然后通過統…

數據結構--順序棧和鏈式棧

http://www.cnblogs.com/jingliming/p/4602458.html 棧是一種限定只在表尾進行插入或刪除操作,棧也是線性表表頭稱為棧的底部,表尾稱為棧的頂部,表為空稱為空棧&#xff0c;棧又稱為后進先出的線性表,棧也有兩種表示:順序棧與鏈式棧順序棧是利用一組地址連續的存儲單元&#xf…

CodeForces - 1144F搜索+簡單圖論

【題目鏈接】Graph Without Long Directed Paths 【題目分析】題目想要講一個無向圖變成一個最長路徑不超過1的有向圖。假如某個邊是從u到v的&#xff0c;那么所有和v相連的都必須是指向v的&#xff0c;所有和u相連的都必須是從u開始的。相當于涂色&#xff0c;相連的節點應該涂…

數據結構--雙鏈表的創建和操作

http://www.cnblogs.com/jingliming/p/4602144.html#0-tsina-1-42616-397232819ff9a47a7b7e80a40613cfe1 一、雙向鏈表的定義 雙向鏈表也叫雙鏈表&#xff0c;是鏈表的一種&#xff0c;它的每個數據結點中都有兩個指針&#xff0c;分別指向直接后繼和直接前驅。所以&#xff0c…

CodeForces - 1152B二進制+思維

【題目鏈接】Neko Performs Cat Furrier Transform 【題目分析】要求將一個數字變成2n-1,通過嘗試我們發現如果將最低位的全零位和對應的全一數字&#xff08;例如11000對應的就是111&#xff09;異或那么數字就會變成想要的結果&#xff08;11111&#xff09; 但是如果前面還有…

C語言文件操作之fgets()

http://blog.csdn.net/daiyutage/article/details/8540932 來說一說fgets(..)函數。 原型 char * fgets(char * s, int n,FILE *stream); 參數&#xff1a; s: 字符型指針&#xff0c;指向存儲讀入數據的緩沖區的地址。 n: 從流中讀入n-1個字符 stream &#xff1a; 指向讀取…

指針與零的比較以及浮點型與零的比較

指針和零的比較 int *p null;if(p ! null){p 20; } 整形和零的比較 int i 0; if(0i) {... } 浮點型和零的比較 判斷一個浮點數是不是零 #define EXP 0.0000000000001 float f 0.00001; if((f > -EXP)&&(f < EXP)) {... } 擴展后 判斷一個浮點數是不…

CodeForces 1138B暴力+剪枝

【題目鏈接】Circus 【題目分析】理解題意以后發現并沒有什么思路&#xff0c;沒有什么算法能用&#xff0c;這個時候就應該想到計算機解題的本質——暴力求解。相應的就要想到剪枝的條件&#xff0c;肯定不能盲目的暴力求解。 總共有四種人&#xff1a;00,01,10,11&#xff0c…

MYSQL錯誤代碼#1045 Access denied for user 'root'@'localhost'

http://blog.csdn.net/lykezhan/article/details/70880845 遇到MYSQL“錯誤代碼#1045 Access denied for user rootlocalhost (using password:YES)” 需要重置root賬號權限密碼&#xff0c;這個一般還真不好解決。 不過&#xff0c;這幾天調試的時候真的遇到了這種問題&#x…

C語言操作符

移位表達式 左移操作符<< 左邊拋棄,右邊補零 右移操作符>> 1.邏輯右移 左邊補零,右邊丟棄 2.算數右移 左邊補符號位,右邊丟棄 注意: 1.左移一位相當于乘2,右移一位相當于除2,并且在內存中存放的是二進制的補碼,且移位操作符只對int型數操作 2.移位操作符不要移動…

棋盤問題——DFS

【題目描述】 在一個給定形狀的棋盤&#xff08;形狀可能是不規則的&#xff09;上面擺放棋子&#xff0c;棋子沒有區別。要求擺放時任意的兩個棋子不能放在棋盤中的同一行或者同一列&#xff0c;請編程求解對于給定形狀和大小的棋盤&#xff0c;擺放k個棋子的所有可行的擺放方…

linux安裝mysql和使用c語言操作數據庫的方法 c語言連接mysql

http://www.jb51.net/article/46139.htm 1. MySQL的安裝與配置&#xff1a; 在Ubuntu下安裝MySQL方法很簡單&#xff0c;使用如下命令&#xff1a; 復制代碼 代碼如下:sudo apt-get install mysql-server安裝的過程中系統會提示設置root密碼&#xff0c;此過程可以跳過&#…

常量變量以及循環

常量 1.三目運算詞 三字母詞表達字符???([??)]??<{??>} 2.循環 1).數組元素以及變量在內存中的分配順序 2)goto語句應用 //電腦關機程序 #include<stdio.h> #include <stdlib.h> #include <string.h> #include <windows.h> int ma…

Dungeon Master——BFS

【題目描述】 You are trapped in a 3D dungeon and need to find the quickest way out! The dungeon is composed of unit cubes which may or may not be filled with rock. It takes one minute to move one unit north, south, east, west, up or down. You cannot move …