UNIX網絡編程——select函數的并發限制和 poll 函數應用舉例

http://blog.csdn.net/chenxun_2010/article/details/50489577

一、用select實現的并發服務器,能達到的并發數,受兩方面限制


? ? ? ?1、一個進程能打開的最大文件描述符限制。這可以通過調整內核參數。可以通過ulimit -n來調整或者使用setrlimit函數設置,?但一個系統所能打開的最大數也是有限的,跟內存大小有關,可以通過cat /proc/sys/fs/file-max?查看

? ? ? ?2、select中的fd_set集合容量的限制(FD_SETSIZE,一般為1024) ,這需要重新編譯內核。


可以寫個測試程序,只建立連接,看看最多能夠建立多少個連接,客戶端程序如下:

[cpp]?view plaincopy
  1. #include?<sys/types.h>??
  2. #include?<sys/socket.h>??
  3. #include?<netinet/in.h>??
  4. #include?<arpa/inet.h>??
  5. #include?<signal.h>??
  6. #include?<stdlib.h>??
  7. #include?<stdio.h>??
  8. #include?<errno.h>??
  9. #include?<string.h>??
  10. ??
  11. #define?ERR_EXIT(m)?\??
  12. ????????do?\??
  13. ????????{?\??
  14. ????????????????perror(m);?\??
  15. ????????????????exit(EXIT_FAILURE);?\??
  16. ????????}?while(0)??
  17. ??
  18. ??
  19. int?main(void)??
  20. {??
  21. ????int?count?=?0;??
  22. ????while(1)??
  23. ????{??
  24. ????????int?sock;??
  25. ????????if?((sock?=?socket(PF_INET,?SOCK_STREAM,?IPPROTO_TCP))?<?0)??
  26. ????????{??
  27. ????????????sleep(4);??
  28. ????????????ERR_EXIT("socket");??
  29. ????????}??
  30. ??
  31. ????????struct?sockaddr_in?servaddr;??
  32. ????????memset(&servaddr,?0,?sizeof(servaddr));??
  33. ????????servaddr.sin_family?=?AF_INET;??
  34. ????????servaddr.sin_port?=?htons(5188);??
  35. ????????servaddr.sin_addr.s_addr?=?inet_addr("127.0.0.1");??
  36. ??
  37. ????????if?(connect(sock,?(struct?sockaddr?*)&servaddr,?sizeof(servaddr))?<?0)??
  38. ????????????ERR_EXIT("connect");??
  39. ??
  40. ????????struct?sockaddr_in?localaddr;??
  41. ????????socklen_t?addrlen?=?sizeof(localaddr);??
  42. ????????if?(getsockname(sock,?(struct?sockaddr?*)&localaddr,?&addrlen)?<?0)??
  43. ????????????ERR_EXIT("getsockname");??
  44. ??
  45. ????????printf("ip=%s?port=%d\n",?inet_ntoa(localaddr.sin_addr),?ntohs(localaddr.sin_port));??
  46. ????????printf("count?=?%d\n",?++count);??
  47. ??
  48. ????}??
  49. ??
  50. ????return?0;??
  51. }??
服務器的代碼serv.c

[cpp]?view plaincopy
  1. #include<stdio.h>??
  2. #include<sys/types.h>??
  3. #include<sys/socket.h>??
  4. #include<unistd.h>??
  5. #include<stdlib.h>??
  6. #include<errno.h>??
  7. #include<arpa/inet.h>??
  8. #include<netinet/in.h>??
  9. #include<string.h>??
  10. #include<signal.h>??
  11. #include<sys/wait.h>??
  12. ??
  13. ??
  14. ??
  15. #define?ERR_EXIT(m)?\??
  16. ????do?{?\??
  17. ????????perror(m);?\??
  18. ????????exit(EXIT_FAILURE);?\??
  19. ????}?while?(0)??
  20. ??
  21. ??
  22. int?main(void)??
  23. {??
  24. ??????
  25. ????signal(SIGPIPE,?SIG_IGN);??
  26. ????int?listenfd;?//被動套接字(文件描述符),即只可以accept,?監聽套接字??
  27. ????if?((listenfd?=?socket(PF_INET,?SOCK_STREAM,?IPPROTO_TCP))?<?0)??
  28. //??listenfd?=?socket(AF_INET,?SOCK_STREAM,?0)????
  29. ????????ERR_EXIT("socket?error");??
  30. ??
  31. ????struct?sockaddr_in?servaddr;??
  32. ????memset(&servaddr,?0,?sizeof(servaddr));??
  33. ????servaddr.sin_family?=?AF_INET;??
  34. ????servaddr.sin_port?=?htons(5188);??
  35. ????servaddr.sin_addr.s_addr?=?htonl(INADDR_ANY);???
  36. ????/*?servaddr.sin_addr.s_addr?=?inet_addr("127.0.0.1");?*/??
  37. ????/*?inet_aton("127.0.0.1",?&servaddr.sin_addr);?*/??
  38. ??????
  39. ????int?on?=?1;??
  40. ????if?(setsockopt(listenfd,?SOL_SOCKET,?SO_REUSEADDR,?&on,?sizeof(on))?<?0)??
  41. ????????ERR_EXIT("setsockopt?error");??
  42. ??
  43. ????if?(bind(listenfd,?(struct?sockaddr*)&servaddr,sizeof(servaddr))?<?0)??
  44. ????????ERR_EXIT("bind?error");??
  45. ??
  46. ????if?(listen(listenfd,?SOMAXCONN)?<?0)?//listen應在socket和bind之后,而在accept之前??
  47. ????????ERR_EXIT("listen?error");??
  48. ??????
  49. ????struct?sockaddr_in?peeraddr;?//傳出參數??
  50. ????socklen_t?peerlen?=?sizeof(peeraddr);?//傳入傳出參數,必須有初始值??
  51. ??????
  52. ????int?conn;?//?已連接套接字(變為主動套接字,即可以主動connect)??
  53. ????int?i;??
  54. ????int?client[FD_SETSIZE];??
  55. ????int?maxi?=?0;?//?client數組中最大不空閑位置的下標??
  56. ????for?(i?=?0;?i?<?FD_SETSIZE;?i++)??
  57. ????????client[i]?=?-1;??
  58. ??
  59. ????int?nready;??
  60. ????int?maxfd?=?listenfd;??
  61. ????fd_set?rset;??
  62. ????fd_set?allset;??
  63. ????FD_ZERO(&rset);??
  64. ????FD_ZERO(&allset);??
  65. ????FD_SET(listenfd,?&allset);??
  66. ??
  67. ????int?count?=?0;??
  68. ????while?(1)?{??
  69. ????????rset?=?allset;??
  70. ????????nready?=?select(maxfd?+?1,?&rset,?NULL,?NULL,?NULL);??
  71. ????????if?(nready?==?-1)?{??
  72. ????????????if?(errno?==?EINTR)??
  73. ????????????????continue;??
  74. ????????????ERR_EXIT("select?error");??
  75. ????????}??
  76. ??
  77. ????????if?(nready?==?0)??
  78. ????????????continue;??
  79. ??
  80. ????????if?(FD_ISSET(listenfd,?&rset))?{??
  81. ??????????
  82. ????????????conn?=?accept(listenfd,?(struct?sockaddr*)&peeraddr,?&peerlen);??//accept不再阻塞??
  83. ????????????if?(conn?==?-1)??
  84. ????????????????ERR_EXIT("accept?error");??
  85. ????????????printf("count?=?%d\n",?++count);??
  86. ????????????for?(i?=?0;?i?<?FD_SETSIZE;?i++)?{??
  87. ????????????????if?(client[i]?<?0)?{??
  88. ????????????????????client[i]?=?conn;??
  89. ????????????????????if?(i?>?maxi)??
  90. ????????????????????????maxi?=?i;??
  91. ????????????????????break;??
  92. ????????????????}???
  93. ????????????}??
  94. ??????????????
  95. ????????????if?(i?==?FD_SETSIZE)?{??
  96. ????????????????fprintf(stderr,?"too?many?clients\n");??
  97. ????????????????exit(EXIT_FAILURE);??
  98. ????????????}??
  99. ??
  100. ????????????printf("recv?connect?ip=%s?port=%d\n",?inet_ntoa(peeraddr.sin_addr),??
  101. ????????????????ntohs(peeraddr.sin_port));??
  102. ??
  103. ????????????FD_SET(conn,?&allset);??
  104. ????????????if?(conn?>?maxfd)??
  105. ????????????????maxfd?=?conn;??
  106. ??
  107. ????????????if?(--nready?<=?0)??
  108. ????????????????continue;??
  109. ????????}??
  110. ??
  111. ????????for?(i?=?0;?i?<=?maxi;?i++)?{??
  112. ????????????conn?=?client[i];??
  113. ????????????if?(conn?==?-1)??
  114. ????????????????continue;??
  115. ??
  116. ????????????if?(FD_ISSET(conn,?&rset))?{??
  117. ??????????????????
  118. ????????????????char?recvbuf[1024]?=?{0};??
  119. ????????????????int?ret?=?read(conn,?recvbuf,?1024);??
  120. ????????????????if?(ret?==?-1)??
  121. ????????????????????ERR_EXIT("read?error");??
  122. ????????????????else?if?(ret??==?0)?{?//客戶端關閉???
  123. ????????????????????printf("client?close?\n");??
  124. ????????????????????FD_CLR(conn,?&allset);??
  125. ????????????????????client[i]?=?-1;??
  126. ????????????????????close(conn);??
  127. ????????????????}??
  128. ??????????
  129. ????????????????fputs(recvbuf,?stdout);??
  130. ????????????????write(conn,?recvbuf,?strlen(recvbuf));??
  131. ??????????????????
  132. ????????????????if?(--nready?<=?0)??
  133. ????????????????????break;???
  134. ????????????}??
  135. ????????}??
  136. ??
  137. ??
  138. ????}??
  139. ??????????
  140. ????return?0;??
  141. }??
  142. ??
  143. /*?select所能承受的最大并發數受?
  144. ?*?1.一個進程所能打開的最大文件描述符數,可以通過ulimit?-n來調整?
  145. ?*???但一個系統所能打開的最大數也是有限的,跟內存有關,可以通過cat?/proc/sys/fs/file-max?查看?
  146. ?*?2.FD_SETSIZE(fd_set)的限制,這個需要重新編譯內核???????????????????????????????????????????????????????????????????????????
  147. ?*/??


huangcheng@ubuntu:~$ ./serv ?
count = 1 ?
recv connect ip=127.0.0.1 port=48370 ?
count = 2 ?
recv connect ip=127.0.0.1 port=48371 ?
count = 3 ?
recv connect ip=127.0.0.1 port=48372 ?
count = 4 ?
recv connect ip=127.0.0.1 port=48373 ?
.................................... ?
recv connect ip=127.0.0.1 port=49389 ?
count = 1020 ?
recv connect ip=127.0.0.1 port=49390 ?



accept error: Too many open files ?
[cpp] view plaincopyprint?
huangcheng@ubuntu:~$ ./cli ?
ip=127.0.0.1 port=46327 ?
count = 1 ?
ip=127.0.0.1 port=46328 ?
count = 2 ?
ip=127.0.0.1 port=46329 ?
count = 3 ?
ip=127.0.0.1 port=46330 ?
count = 4 ?
ip=127.0.0.1 port=46331 ?
count = 5 ?
ip=127.0.0.1 port=46332 ?
count = 6 ?
ip=127.0.0.1 port=46333 ?
....................... ?
ip=127.0.0.1 port=47345 ?
count = 1020 ?
ip=127.0.0.1 port=47346 ?
count = 1021 ?
socket: Too many open files ?


輸出太多條目,上面只截取最后幾條,從中可以看出對于客戶端,最多只能開啟1021個連接套接字,因為總共是1024個,還得除去0、1、2。而服務器端只能accept 返回1020個已連接套接字,因為除了0、1、2之外還有一個監聽套接字,客戶端某一個套接字(不一定是最后一個)雖然已經建立了連接,在已完成連接隊列中,但accept 返回時達到最大描述符限制,返回錯誤,打印提示信息。


? ? ? ?也許有人會注意到上面有一行 sleep(4);當客戶端調用socket準備創建第1022個套接字時,如上所示也會提示錯誤,此時socket函數返回-1出錯,如果沒有睡眠4s后再退出進程會有什么問題呢?如果直接退出進程,會將客戶端所打開的所有套接字關閉掉,即向服務器端發送了很多FIN段,而此時也許服務器端還一直在accept ,即還在從已連接隊列中返回已連接套接字,此時服務器端除了關心監聽套接字的可讀事件,也開始關心前面已建立連接的套接字的可讀事件,read 返回0,所以會有很多 client close 字段 參雜在條目的輸出中,還有個問題就是,因為read 返回0,服務器端會將自身的已連接套接字關閉掉,那么也許剛才說的客戶端某一個連接會被accept 返回,即測試不出服務器端真正的并發容量。

  1. huangcheng@ubuntu:~$?./serv??
  2. count?=?1??
  3. recv?connect?ip=127.0.0.1?port=50413??
  4. count?=?2??
  5. ....................................??
  6. client?close??
  7. client?close??
  8. client?close??
  9. client?close??
  10. ...................................??
  11. recv?connect?ip=127.0.0.1?port=51433??
  12. client?close??
  13. count?=?1021??
  14. recv?connect?ip=127.0.0.1?port=51364??
  15. client?close??
  16. client?close??
? ? ? 可以看到輸出參雜著client close,且這次的count 達到了1021,原因就是服務器端前面已經有些套接字關閉了,所以accept 創建套接字不會出錯,服務器進程也不會因為出錯而退出,可以看到最后接收到的一個連接端口是51364,即不一定是客戶端的最后一個連接。

二、poll 函數應用舉例


[cpp]?view plaincopy
  1. #include?<poll.h>??
  2. int?poll(struct?pollfd?*fds,?nfds_t?nfds,?int?timeout);??
參數1:結構體數組指針

[cpp]?view plaincopy
  1. struct?pollfd?{??
  2. ????int???fd;?????????/*?file?descriptor?*/??
  3. ????short?events;?????/*?requested?events?*/??
  4. ????short?revents;????/*?returned?events?*/??
  5. };??

結構體中的fd 即套接字描述符,events 即感興趣的事件,如下圖所示,revents 即返回的事件。


參數2:結構體數組的成員個數,即文件描述符個數。

參數3:即超時時間,若為-1,表示永不超時。


? ? ? ?poll 跟 select 還是很相似的,比較重要的區別在于poll 所能并發的個數跟FD_SETSIZE無關,只跟一個進程所能打開的文件描述符個數有關,可以在select 程序的基礎上修改成poll 程序,在運行服務器端程序之前,使用ulimit -n 2048?將限制改成2048個,注意在運行客戶端進程的終端也需更改,因為客戶端也會有所限制,這只是臨時性的更改,因為子進程會繼承這個環境參數,而我們是在bash命令行啟動程序的,故在進程運行期間,文件描述符的限制為2048個。

使用poll 函數的服務器端程序如下:

[cpp]?view plaincopy
  1. #include<stdio.h>??
  2. #include<sys/types.h>??
  3. #include<sys/socket.h>??
  4. #include<unistd.h>??
  5. #include<stdlib.h>??
  6. #include<errno.h>??
  7. #include<arpa/inet.h>??
  8. #include<netinet/in.h>??
  9. #include<string.h>??
  10. #include<signal.h>??
  11. #include<sys/wait.h>??
  12. #include<poll.h>??
  13. ??
  14. #define?ERR_EXIT(m)?\??
  15. ????do?{?\??
  16. ????????perror(m);?\??
  17. ????????exit(EXIT_FAILURE);?\??
  18. ????}?while?(0)??
  19. ??
  20. ??
  21. int?main(void)??
  22. {??
  23. ????int?count?=?0;??
  24. ????signal(SIGPIPE,?SIG_IGN);??
  25. ????int?listenfd;?//被動套接字(文件描述符),即只可以accept,?監聽套接字??
  26. ????if?((listenfd?=?socket(PF_INET,?SOCK_STREAM,?IPPROTO_TCP))?<?0)??
  27. ????????//??listenfd?=?socket(AF_INET,?SOCK_STREAM,?0)??
  28. ????????ERR_EXIT("socket?error");??
  29. ??
  30. ????struct?sockaddr_in?servaddr;??
  31. ????memset(&servaddr,?0,?sizeof(servaddr));??
  32. ????servaddr.sin_family?=?AF_INET;??
  33. ????servaddr.sin_port?=?htons(5188);??
  34. ????servaddr.sin_addr.s_addr?=?htonl(INADDR_ANY);??
  35. ????/*?servaddr.sin_addr.s_addr?=?inet_addr("127.0.0.1");?*/??
  36. ????/*?inet_aton("127.0.0.1",?&servaddr.sin_addr);?*/??
  37. ??
  38. ????int?on?=?1;??
  39. ????if?(setsockopt(listenfd,?SOL_SOCKET,?SO_REUSEADDR,?&on,?sizeof(on))?<?0)??
  40. ????????ERR_EXIT("setsockopt?error");??
  41. ??
  42. ????if?(bind(listenfd,?(struct?sockaddr?*)&servaddr,?sizeof(servaddr))?<?0)??
  43. ????????ERR_EXIT("bind?error");??
  44. ??
  45. ????if?(listen(listenfd,?SOMAXCONN)?<?0)?//listen應在socket和bind之后,而在accept之前??
  46. ????????ERR_EXIT("listen?error");??
  47. ??
  48. ????struct?sockaddr_in?peeraddr;?//傳出參數??
  49. ????socklen_t?peerlen?=?sizeof(peeraddr);?//傳入傳出參數,必須有初始值??
  50. ??
  51. ????int?conn;?//?已連接套接字(變為主動套接字,即可以主動connect)??
  52. ????int?i;??
  53. ??
  54. ????struct?pollfd?client[2048];??
  55. ????int?maxi?=?0;?//client[i]最大不空閑位置的下標??
  56. ??
  57. ????for?(i?=?0;?i?<?2048;?i++)??
  58. ????????client[i].fd?=?-1;??
  59. ??
  60. ????int?nready;??
  61. ????client[0].fd?=?listenfd;??
  62. ????client[0].events?=?POLLIN;??
  63. ??
  64. ????while?(1)??
  65. ????{??
  66. ????????/*?poll檢測[0,?maxi?+?1)?*/??
  67. ????????nready?=?poll(client,?maxi?+?1,?-1);??
  68. ????????if?(nready?==?-1)??
  69. ????????{??
  70. ????????????if?(errno?==?EINTR)??
  71. ????????????????continue;??
  72. ????????????ERR_EXIT("poll?error");??
  73. ????????}??
  74. ??
  75. ????????if?(nready?==?0)??
  76. ????????????continue;??
  77. ??
  78. ????????if?(client[0].revents?&?POLLIN)??
  79. ????????{??
  80. ??
  81. ????????????conn?=?accept(listenfd,?(struct?sockaddr?*)&peeraddr,?&peerlen);?//accept不再阻塞??
  82. ????????????if?(conn?==?-1)??
  83. ????????????????ERR_EXIT("accept?error");??
  84. ??
  85. ????????????for?(i?=?1;?i?<?2048;?i++)??
  86. ????????????{??
  87. ????????????????if?(client[i].fd?<?0)??
  88. ????????????????{??
  89. ????????????????????client[i].fd?=?conn;??
  90. ????????????????????if?(i?>?maxi)??
  91. ????????????????????????maxi?=?i;??
  92. ????????????????????break;??
  93. ????????????????}??
  94. ????????????}??
  95. ??
  96. ????????????if?(i?==?2048)??
  97. ????????????{??
  98. ????????????????fprintf(stderr,?"too?many?clients\n");??
  99. ????????????????exit(EXIT_FAILURE);??
  100. ????????????}??
  101. ??
  102. ????????????printf("count?=?%d\n",?++count);??
  103. ????????????printf("recv?connect?ip=%s?port=%d\n",?inet_ntoa(peeraddr.sin_addr),??
  104. ???????????????????ntohs(peeraddr.sin_port));??
  105. ??
  106. ????????????client[i].events?=?POLLIN;??
  107. ??
  108. ????????????if?(--nready?<=?0)??
  109. ????????????????continue;??
  110. ????????}??
  111. ??
  112. ????????for?(i?=?1;?i?<=?maxi;?i++)??
  113. ????????{??
  114. ????????????conn?=?client[i].fd;??
  115. ????????????if?(conn?==?-1)??
  116. ????????????????continue;??
  117. ????????????if?(client[i].revents?&?POLLIN)??
  118. ????????????{??
  119. ??
  120. ????????????????char?recvbuf[1024]?=?{0};??
  121. ????????????????int?ret?=?read(conn,?recvbuf,?1024);??
  122. ????????????????if?(ret?==?-1)??
  123. ????????????????????ERR_EXIT("readline?error");??
  124. ????????????????else?if?(ret??==?0)???//客戶端關閉??
  125. ????????????????{??
  126. ????????????????????printf("client??close?\n");??
  127. ????????????????????client[i].fd?=?-1;??
  128. ????????????????????close(conn);??
  129. ????????????????}??
  130. ??
  131. ????????????????fputs(recvbuf,?stdout);??
  132. ????????????????write(conn,?recvbuf,?strlen(recvbuf));??
  133. ??
  134. ????????????????if?(--nready?<=?0)??
  135. ????????????????????break;??
  136. ????????????}??
  137. ????????}??
  138. ??
  139. ??
  140. ????}??
  141. ??
  142. ????return?0;??
  143. }??
  144. ??
  145. /*?poll?只受一個進程所能打開的最大文件描述符限制,這個可以使用ulimit?-n調整?*/??

參照前面對 select 函數 的解釋不難理解上面的程序,就不再贅述了。來看一下輸出:


[cpp]?view plaincopy
  1. root@ubuntu:/home/huangcheng#?ulimit?-n?2048??
  2. root@ubuntu:/home/huangcheng#?su?-?huangcheng??
  3. huangcheng@ubuntu:~$?ulimit?-n??
  4. 2048??
  5. huangcheng@ubuntu:~$?./serv??
  6. ...........................??
  7. count?=?2042??
  8. recv?connect?ip=127.0.0.1?port=54499??
  9. count?=?2043??
  10. recv?connect?ip=127.0.0.1?port=54500??
  11. count?=?2044??
  12. recv?connect?ip=127.0.0.1?port=54501??
  13. accept?error:?Too?many?open?files??
[cpp]?view plaincopy
  1. root@ubuntu:/home/huangcheng#?ulimit?-n?2048??
  2. root@ubuntu:/home/huangcheng#?su?-?huangcheng??
  3. huangcheng@ubuntu:~$?ulimit?-n??
  4. 2048??
  5. huangcheng@ubuntu:~$./cli??
  6. ..........................??
  7. ip=127.0.0.1?port=54499??
  8. count?=?2043??
  9. ip=127.0.0.1?port=54500??
  10. count?=?2044??
  11. ip=127.0.0.1?port=54501??
  12. count?=?2045??
  13. socket:?Too?many?open?files??
? ? ? ?可以看到現在最大的連接數已經是2045個了,雖然服務器端有某個連接沒有accept 返回。即poll 比 select 能夠承受更多的并發連接,只受一個進程所能打開的最大文件描述符個數限制。可以通過ulimit -n ?修改,但一個系統所能打開的文件描述符個數也是有限的,這跟系統的內存大小有關系,所以說也不是可以無限地并 發,可以查看一下本機的容量:

[cpp]?view plaincopy
  1. huangcheng@ubuntu:~$?cat?/proc/sys/fs/file-max??
  2. 101598??
本機是虛擬機,內存2G,能夠打開的文件描述符個數大約在10w個左右。


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

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

相關文章

【Java學習筆記二】繼承和多態

與C不同的是&#xff0c;在Java中&#xff0c;一個類只能直接繼承另一個類&#xff0c;而不允許繼承多個類&#xff0c;這個新類稱為繼承類、派生類或者子類&#xff0c;而被繼承的類稱為基類或者父類。 繼承類能夠繼承基類的群不屬性和行為。 面向對象程序設計的三大特點為&…

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

http://blog.csdn.net/robertkun/article/details/52269313 參考&#xff1a;http://www.cnblogs.com/Anker/p/3261006.html 使用poll實現的io多路復用服務端和客戶端。 客戶端通過子進程創建多個客戶端連接。 客戶端每隔1秒向服務端發送一個時間戳&#xff0c; 服務端接收到時…

【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…