基于epoll的簡單的http服務器

http://blog.csdn.net/fangjian1204/article/details/34415651

http服務器已經可以處理并發連接,支持多個客戶端并發訪問,每個連接可以持續讀寫數據,當然,這只是一個簡單的學習例子,還有很多bug,發表出來只是希望大家可以互相學習,我也在不斷的改進,希望大家有什么意見可以多多指點,謝謝


server.h

[cpp]?view plain?copy
  1. /*?
  2. ?*?server.h?
  3. ?*?
  4. ?*??Created?on:?Jun?23,?2014?
  5. ?*??????Author:?fangjian?
  6. ?*/??
  7. ??
  8. ??
  9. #ifndef?SERVER_H_??
  10. #define?SERVER_H_??
  11. ??
  12. #include?"epoll_event.h"??
  13. ??
  14. struct?web_event_t;??
  15. struct?web_connection_t??
  16. {??
  17. ????int?fd;??
  18. ??
  19. ????int?state;//當前處理到哪個階段??
  20. ????struct?web_event_t*?read_event;??
  21. ????struct?web_event_t*?write_event;??
  22. ????char*?querybuf;??
  23. ????int?query_start_index;//請求數據的當前指針??
  24. ????int?query_end_index;//請求數據的下一個位置??
  25. ????int?query_remain_len;//可用空間??
  26. ??
  27. ????char?method[8];??
  28. ????char?uri[128];??
  29. ????char?version[16];??
  30. ????char?host[128];??
  31. ????char?accept[128];??
  32. ????char?conn[20];??
  33. };??
  34. ??
  35. struct?server??
  36. {??
  37. ????int?epollfd;??
  38. };??
  39. ??
  40. void?web_epoll_ctl(int?epollfd,int?ctl,int?fd,int?flag);??
  41. int?setnonblocking(int?fd);??
  42. void?initConnection(web_connection_t*?&conn);??
  43. void?web_accept(struct?web_connection_t*?conn);??
  44. void?read_request(?struct?web_connection_t*?conn?);??
  45. void?process_request_line(struct?web_connection_t*?conn);??
  46. void?process_head(struct?web_connection_t*?conn);??
  47. void?process_body(struct?web_connection_t*?conn);??
  48. void?send_response(struct?web_connection_t*?conn);??
  49. void?try_to_enlarge_buffer(struct?web_connection_t&?conn);??
  50. void?empty_event_handler(struct?web_connection_t*?conn);??
  51. void?close_conn(?struct?web_connection_t*?conn?);??
  52. ??
  53. #endif?/*?SERVER_H_?*/??

server.cpp

[cpp]?view plain?copy
  1. /*?
  2. ?*?server.cpp?
  3. ?*?
  4. ?*??Created?on:?Jun?23,?2014?
  5. ?*??????Author:?fangjian?
  6. ?*/??
  7. ??
  8. #include?"server.h"??
  9. #include?"epoll_event.h"??
  10. ??
  11. #include?<stdio.h>??
  12. #include?<netinet/in.h>??
  13. #include?<arpa/inet.h>??
  14. #include?<string.h>??
  15. #include?<stdlib.h>??
  16. #include?<fcntl.h>??
  17. #include<signal.h>??
  18. #include?<sys/socket.h>??
  19. #include?<sys/epoll.h>??
  20. #include?<sys/stat.h>??
  21. #include?<sys/sendfile.h>??
  22. #include?<iostream>??
  23. using?namespace?std;??
  24. ??
  25. int?main(int?argc,char*?argv[])??
  26. {??
  27. ????const?char*?ip?=?"127.0.0.1";??
  28. ????int?port?=??8083;??
  29. ??
  30. ????signal(SIGPIPE,SIG_IGN);//原因:http://blog.sina.com.cn/s/blog_502d765f0100kopn.html??
  31. ??
  32. ????int?listenfd?=?socket(AF_INET,SOCK_STREAM,0);??
  33. ????struct?sockaddr_in?address;??
  34. ????bzero(&address,sizeof(address));??
  35. ????address.sin_family?=?AF_INET;??
  36. ????inet_pton(AF_INET,ip,&address.sin_addr);??
  37. ????address.sin_port?=?htons(port);??
  38. ????bind(listenfd,(struct?sockaddr*)&address,sizeof(address));??
  39. ????listen(listenfd,50);??
  40. ??
  41. ????web_connection_t*?conn?=?NULL;??
  42. ????epoll_init_event(conn);??
  43. ????initConnection(conn);//創建一個用于接受連接的結構體??
  44. ????if(conn?==?NULL){printf("---創建監聽結構體失敗---\n");return?-1;};//創建監聽結構體??
  45. ??
  46. ????conn->fd?=?listenfd;??
  47. ????conn->read_event->handler?=?web_accept;??
  48. ????epoll_add_event(conn,EPOLLIN?|?EPOLLERR);??
  49. ??
  50. ????setnonblocking(listenfd);??
  51. ??
  52. ????fork();??
  53. ??
  54. ????ngx_epoll_process_events();//進入事件循環,等待事件到達??
  55. }??
  56. void?initConnection(web_connection_t*?&conn)??
  57. {??
  58. ????conn?=?(web_connection_t*)malloc(sizeof(web_connection_t));??
  59. ????conn->read_event?=?(web_event_t*)malloc(sizeof(web_event_t));??
  60. ????conn->write_event?=?(web_event_t*)malloc(sizeof(web_event_t));??
  61. ????conn->state?=?ACCEPT;??
  62. ??
  63. ????conn->querybuf?=?(char*)malloc(QUERY_INIT_LEN);??
  64. ????if(!conn->querybuf)??
  65. ????{??
  66. ????????printf("?malloc?error\n");??
  67. ????????return;??
  68. ????}??
  69. ????conn->query_start_index?=?0;??
  70. ????conn->query_end_index?=?0;??
  71. ????conn->query_remain_len?=?QUERY_INIT_LEN;??
  72. }??
  73. ??
  74. int?setnonblocking(int?fd)??
  75. {??
  76. ????int?old_option?=?fcntl(fd,F_GETFL);??
  77. ????int?new_option?=?old_option?|?O_NONBLOCK;??
  78. ????fcntl(fd,F_SETFL,new_option);??
  79. ????return?old_option;??
  80. }??
  81. ??
  82. void?web_accept(web_connection_t*?conn)??
  83. {??
  84. ????printf("-----------accept-------\n");??
  85. ????struct?sockaddr?*?client_address;??
  86. ????socklen_t?client_addrlength?=?sizeof(client_address);??
  87. ????int?connfd?=?accept(conn->fd,(struct?sockaddr*)&(client_address),&client_addrlength);??
  88. ????if(connfd?==?-1)??
  89. ????{??
  90. ????????printf("accept?error\n");??
  91. ????????return;??
  92. ????}??
  93. ????web_connection_t*?new_conn?=?NULL;??
  94. ????initConnection(new_conn);//創建一個新的連接結構體??
  95. ????if(new_conn?==?NULL){printf("---創建連接結構體失敗---\n");return;};??
  96. ??
  97. ????new_conn->fd?=?connfd;??
  98. ????new_conn->state?=?READ;??
  99. ????new_conn->read_event->handler?=?read_request;??
  100. ????epoll_add_event(new_conn,EPOLLIN?|?EPOLLERR);??
  101. ??
  102. ????setnonblocking(connfd);??
  103. }??
  104. void?read_request(?struct?web_connection_t*?conn?)??
  105. {??
  106. ????printf("-----------read_begin-------\n");??
  107. ??
  108. ????int?len,fd?=?conn->fd;??
  109. ????while(true)??
  110. ????{??
  111. ????????/*?嘗試增加緩沖區空間?*/??
  112. ????????try_to_enlarge_buffer(*conn);??
  113. ????????len=?recv(fd,conn->querybuf?+?conn->query_end_index,conn->query_remain_len,0);??
  114. ????????if(len?<?0)??
  115. ????????{??
  116. ????????????printf("----數據讀取完畢-----\n");??
  117. ????????????break;//表示當前數據讀取完畢,不是出錯??
  118. ????????}??
  119. ????????else?if(len?>?0)??
  120. ????????{??
  121. ????????????conn->query_end_index?+=?len;??
  122. ????????????conn->query_remain_len-=?len;??
  123. ????????}??
  124. ????????else?if(len?==?0)??
  125. ????????{??
  126. ????????????printf("----連接關閉-----\n");??
  127. ????????????epoll_del_event(conn);??
  128. ????????????close_conn(conn?);??
  129. ????????????return?;??
  130. ????????}??
  131. ????}??
  132. ????cout?<<?"-----客戶端的內容是?"?<<?endl;??
  133. ??
  134. ????cout?<<?conn->querybuf?<<?endl;??
  135. ??
  136. ????process_request_line(conn);??
  137. ??
  138. ????return?;??
  139. }??
  140. void?process_request_line(struct?web_connection_t*?conn)??
  141. {??
  142. ????int?len;??
  143. ????char*?ptr?=?strpbrk(conn->querybuf?+?conn->query_start_index,"?\t");??
  144. ????if(?!ptr)??
  145. ????{??
  146. ????????printf("請求行解析失敗\n");??
  147. ????????return;??
  148. ????}??
  149. ????len?=?ptr?-?conn->querybuf?-?conn->query_start_index;??
  150. ????strncpy(conn->method,conn->querybuf?+?conn->query_start_index,len);??
  151. ????cout?<<"metnod="<<conn->method<<endl;??
  152. ??
  153. ????conn->query_start_index?+=?(len+1);??
  154. ????ptr?=?strpbrk(conn->querybuf?+?conn->query_start_index,"?\t");??
  155. ????if(?!ptr)??
  156. ????{??
  157. ????????printf("請求行解析失敗\n");??
  158. ????????return;??
  159. ????}??
  160. ????len?=?ptr?-?conn->querybuf?-?conn->query_start_index;??
  161. ????strncpy(conn->uri,conn->querybuf?+?conn->query_start_index,len);??
  162. ????cout?<<?"uri="<<conn->uri<<endl;??
  163. ??
  164. ????conn->query_start_index?+=?(len+1);??
  165. ????ptr?=?strpbrk(conn->querybuf,"\n");//先是回車\r,再是換行\n??
  166. ????if(!ptr)??
  167. ????{??
  168. ????????printf("請求行解析失敗\n");??
  169. ????????return;??
  170. ????}??
  171. ????len?=?ptr?-?conn->querybuf?-?conn->query_start_index;??
  172. ????strncpy(conn->version,conn->querybuf?+?conn->query_start_index,len);??
  173. ????cout?<<?"version="<<conn->version<<endl;??
  174. ????conn->query_start_index?+=?(len+1);??
  175. ??
  176. ????cout?<<"-----請求行解析完畢----------"<<endl;??
  177. ??
  178. ????process_head(conn);??
  179. }??
  180. ??
  181. void?process_head(struct?web_connection_t*?conn)??
  182. {??
  183. ????cout?<<?"-------開始解析首部------"?<<?endl;??
  184. ??
  185. ????char*?end_line;??
  186. ????int?len;??
  187. ??
  188. ????while(true)??
  189. ????{??
  190. ????????end_line?=?strpbrk(conn->querybuf?+?conn->query_start_index,"\n");??
  191. ????????len?=?end_line?-?conn->querybuf?-?conn->query_start_index;??
  192. ????????if(len?==?1)??
  193. ????????{??
  194. ????????????printf("解析完畢\n");??
  195. ????????????conn->query_start_index?+=?(len?+1);??
  196. ????????????cout?<<?conn->querybuf?+?conn->query_start_index?<<?endl;??
  197. ????????????break;??
  198. ????????}??
  199. ????????else??
  200. ????????{??
  201. ????????????if(strncasecmp(conn->querybuf+conn->query_start_index,"Host:",5)?==?0)??
  202. ????????????{??
  203. ????????????????strncpy(conn->host,conn->querybuf+conn->query_start_index?+?6,len-6);??
  204. ????????????????cout?<<?"host="<<conn->host<<endl;??
  205. ????????????}??
  206. ????????????else?if(strncasecmp(conn->querybuf+conn->query_start_index,"Accept:",7)?==?0)??
  207. ????????????{??
  208. ????????????????strncpy(conn->accept,conn->querybuf+conn->query_start_index?+?8,len-8);??
  209. ????????????????cout?<<"accept="<<conn->accept?<<endl;??
  210. ????????????}??
  211. ????????????else?if(strncasecmp(conn->querybuf+conn->query_start_index,"Connection:",11)?==?0)??
  212. ????????????{??
  213. ????????????????strncpy(conn->conn,conn->querybuf+conn->query_start_index?+?12,len-12);??
  214. ????????????????cout?<<"connection="<<conn->conn?<<endl;??
  215. ????????????}??
  216. ????????????else??
  217. ????????????{??
  218. ????????????}??
  219. ????????????conn->query_start_index?+=?(len?+1);??
  220. ????????}??
  221. ????}??
  222. ????process_body(conn);??
  223. ????printf("----首部解析完畢----------\n");??
  224. }??
  225. void?process_body(struct?web_connection_t*?conn)??
  226. {??
  227. ????if(conn->query_start_index?==?conn->query_end_index)??
  228. ????{??
  229. ????????printf("---包體為空----\n");??
  230. ????}??
  231. ????else??
  232. ????{??
  233. ????????printf("---丟體包體-----\n");??
  234. ????}??
  235. ????conn->query_start_index?=?conn->query_end_index?=?0;??
  236. ??
  237. ????conn->state?=?SEND_DATA;??
  238. ????conn->write_event->handler?=?send_response;??
  239. ????conn->read_event->handler?=?empty_event_handler;//讀事件回調函數設置為空??
  240. ????epoll_mod_event(conn,EPOLLOUT?|?EPOLLERR);??
  241. }??
  242. void?send_response(struct?web_connection_t*?conn)??
  243. {??
  244. ????char?path[128]?=?"http";//根目錄下的文件夾??
  245. ????int?len?=?strlen(conn->uri);??
  246. ????memcpy(path+4,conn->uri,len);??
  247. ????len?+=?4;??
  248. ????path[len]?=?'\0';//很重要??
  249. ??
  250. ????int?filefd?=?open(path,O_RDONLY);??
  251. ????if(filefd?<?0)??
  252. ????{??
  253. ????????cout?<<?"無法打開該文件"?<<endl;??
  254. ????????return?;??
  255. ????}??
  256. ????struct?stat?stat_buf;??
  257. ????fstat(filefd,&stat_buf);??
  258. ????sendfile(conn->fd,filefd,NULL,stat_buf.st_size);??
  259. ????close(filefd);??
  260. ??
  261. ????//close(conn->fd);//如果不關閉該連接socket,則瀏覽器一直在加載,如何解決,保持keep-alive???
  262. ??
  263. ????conn->state?=?READ;??
  264. ????conn->read_event->handler?=?read_request;??
  265. ????epoll_mod_event(conn,EPOLLIN?|?EPOLLERR);??
  266. ??
  267. ????//sleep(2);??
  268. }??
  269. ??
  270. void?try_to_enlarge_buffer(struct?web_connection_t&?conn)??
  271. {??
  272. ????if(conn.query_remain_len??<?REMAIN_BUFFER)??
  273. ????{??
  274. ????????int?new_size?=?strlen(conn.querybuf)?+?QUERY_INIT_LEN;??
  275. ????????conn.querybuf?=?(char*)realloc(conn.querybuf,new_size);??
  276. ????????conn.query_remain_len??=?new_size?-?conn.query_end_index;??
  277. ????}??
  278. }??
  279. void?empty_event_handler(struct?web_connection_t*?conn)??
  280. {??
  281. ??
  282. }??
  283. //關閉一個連接??
  284. void?close_conn(?struct?web_connection_t*?conn?)??
  285. {??
  286. ????static?int?count?=?0;??
  287. ????count?++;??
  288. ????printf("關閉第%d個連接\n",count);??
  289. ??
  290. ????close(?conn->fd);??
  291. ????free(conn->querybuf);??
  292. ????free(conn->read_event);??
  293. ????free(conn->write_event);??
  294. ????free(conn);??
  295. }??

epoll_event.h

[cpp]?view plain?copy
  1. /*?
  2. ?*?event.h?
  3. ?*?
  4. ?*??Created?on:?Jun?25,?2014?
  5. ?*??????Author:?fangjian?
  6. ?*/??
  7. ??
  8. #ifndef?EVENT_H_??
  9. #define?EVENT_H_??
  10. ??
  11. #include?<netinet/in.h>??
  12. #include?"server.h"??
  13. #define?MAX_EVENT_NUMBER?10000??
  14. #define?QUERY_INIT_LEN??1024??
  15. #define?REMAIN_BUFFER??512??
  16. ??
  17. /*?以下是處理機的狀態?*/??
  18. #define?ACCEPT?1??
  19. #define?READ?2??
  20. #define?QUERY_LINE?4??
  21. #define?QUERY_HEAD?8??
  22. #define?QUERY_BODY?16??
  23. #define?SEND_DATA?32??
  24. ??
  25. struct?web_connection_t;??
  26. ??
  27. typedef?void?(*event_handler_pt)(web_connection_t*?conn);??
  28. ??
  29. //每一個事件都由web_event_t結構體來表示??
  30. struct?web_event_t??
  31. {??
  32. ????/*為1時表示事件是可寫的,通常情況下,它表示對應的TCP連接目前狀態是可寫的,也就是連接處于可以發送網絡包的狀態*/??
  33. ????unsigned?????????write:1;??
  34. ????/*為1時表示此事件可以建立新的連接,通常情況下,在ngx_cycle_t中的listening動態數組中,每一個監聽對象ngx_listening_t對應的讀事件中?
  35. ????的accept標志位才會是1*/??
  36. ????unsigned?????????accept:1;??
  37. ????//為1時表示當前事件是活躍的,這個狀態對應著事件驅動模塊處理方式的不同,例如:在添加事件、刪除事件和處理事件時,該標志位的不同都會對應著不同的處理方式??
  38. ????unsigned?????????active:1;??
  39. ????unsigned?????????oneshot:1;??
  40. ????unsigned?????????eof:1;//為1時表示當前處理的字符流已經結束??
  41. ????unsigned?????????error:1;//為1時表示事件處理過程中出現了錯誤??
  42. ??
  43. ????event_handler_pt??handler;//事件處理方法,每個消費者模塊都是重新實現它??
  44. ????unsigned?????????closed:1;//為1時表示當前事件已經關閉??
  45. };??
  46. ??
  47. void?epoll_init_event(web_connection_t*?&conn);??
  48. void?epoll_add_event(web_connection_t*?conn,int?flag);??
  49. void?epoll_mod_event(web_connection_t*?conn,int?flag);??
  50. void?epoll_del_event(web_connection_t*?conn);??
  51. int?ngx_epoll_process_events();??
  52. #endif?/*?EVENT_H_?*/??

epoll_event.cpp

[cpp]?view plain?copy
  1. /*?
  2. ?*?event.cpp?
  3. ?*?
  4. ?*??Created?on:?Jun?25,?2014?
  5. ?*??????Author:?fangjian?
  6. ?*/??
  7. ??
  8. #include?"epoll_event.h"??
  9. #include?<sys/epoll.h>??
  10. #include?<unistd.h>??
  11. #include?<stdio.h>??
  12. #include?<stdlib.h>??
  13. ??
  14. static?int??ep?=?-1;//epoll對象的描述符,每個進程只有一個??
  15. ??
  16. void?epoll_init_event(web_connection_t*?&conn)??
  17. {??
  18. ????ep?=?epoll_create(1024);??
  19. }??
  20. ??
  21. /*?添加事件,conn已經設置好回調函數和fd了?*/??
  22. void?epoll_add_event(web_connection_t*?conn,int?flag)??
  23. {??
  24. ????epoll_event?ee;??
  25. ????int?fd?=?conn->fd;??
  26. ????ee.data.ptr?=?(void*)conn;??
  27. ????ee.events?=?flag;??
  28. ????epoll_ctl(ep,EPOLL_CTL_ADD,fd,&ee);??
  29. }??
  30. ??
  31. /*?修改事件,event已經設置好回調函數和fd了?*/??
  32. void?epoll_mod_event(web_connection_t*?conn,int?flag)??
  33. {??
  34. ????epoll_event?ee;??
  35. ????int?fd?=?conn->fd;??
  36. ????ee.data.ptr?=?(void*)conn;??
  37. ????ee.events?=?flag;??
  38. ????epoll_ctl(ep,EPOLL_CTL_MOD,fd,&ee);??
  39. }??
  40. ??
  41. //刪除該描述符上的所有事件,若想只刪除讀事件或寫事件,則把相應的事件設置為空函數??
  42. void?epoll_del_event(web_connection_t*?conn)??
  43. {??
  44. ????epoll_ctl(?ep,?EPOLL_CTL_DEL,?conn->fd,?0?);//刪除事件最后一個參數為0??
  45. }??
  46. //事件循環函數??
  47. int?ngx_epoll_process_events()??
  48. {??
  49. ????epoll_event?event_list[MAX_EVENT_NUMBER];??
  50. ????while(true)??
  51. ????{??
  52. ????????int?number?=?epoll_wait(ep,event_list,MAX_EVENT_NUMBER,-1);??
  53. ??
  54. ????????printf("number=%d\n",number);??
  55. ????????printf("當前進程ID為:?%d?\n",getpid());??
  56. ??
  57. ????????int?i;??
  58. ????????for(i?=?0;i?<?number;i++)??
  59. ????????{??
  60. ????????????web_connection_t*?conn?=?(web_connection_t*)(event_list[i].data.ptr);??
  61. ????????????int?socket?=?conn->fd;//當前觸發的fd??
  62. ????????????//讀事件??
  63. ????????????if?(?event_list[i].events?&?EPOLLIN?)??
  64. ????????????{??
  65. ????????????????conn->read_event->handler(conn);??
  66. ????????????}??
  67. ????????????//寫事件??
  68. ????????????else?if(?event_list[i].events?&?EPOLLOUT?)??
  69. ????????????{??
  70. ????????????????conn->write_event->handler(conn);??
  71. ????????????}??
  72. ????????????else?if(?event_list[i].events?&?EPOLLERR?)??
  73. ????????????{??
  74. ??
  75. ????????????}??
  76. ????????}??
  77. ????}??
  78. ????return?0;??
  79. }??

使用方法:

服務器使用方法:直接運行即可
客戶端使用方法:編譯客戶端代碼,然后 ./client 127.0.0.1 8083 5(最后一個代表客戶端進程數)
本程序在linux平臺下測試成功

免費代碼下載地址:http://download.csdn.net/detail/fangjian1204/7575477


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

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

相關文章

C++單例模式簡單實現

有時候我們需要某個類只能被實例化一次&#xff0c;并且其他類都可以訪問到這個類&#xff0c;就需要這種設計模式。 例如我們想要做個資源管理器&#xff0c;顯然這個管理器只能有一個。 這種模式有很多實現方式&#xff0c;這里介紹最簡單的一種&#xff0c;想要了解更多可…

Linux C++ 實現線程池

http://blog.csdn.net/qq_25425023/article/details/53914609 線程池中的線程&#xff0c;在任務隊列為空的時候&#xff0c;等待任務的到來&#xff0c;任務隊列中有任務時&#xff0c;則依次獲取任務來執行&#xff0c;任務隊列需要同步。 Linux線程同步有多種方法&#xff…

C++制表符

制表符的轉義字符為\t&#xff0c;一般情況下長度為8個空格&#xff0c;這里的8個指的是從上一個字符串的開頭開始算&#xff0c;往后數8個&#xff0c;不夠的話就補空格。 如果前面的字符串的長度大于等于8個&#xff0c;例如前面字符串的長度為x,那么就會補(8-x%8)個空格 例…

C++派生類含有成員對象構造函數析構函數順序

參考博客&#xff1a;傳送門1 當類中含有對象成員時&#xff1a; 類的構造函數要包含對成員對象的初始化&#xff0c;如果構造函數的成員初始化列表沒有包含對成員對象的初始化&#xff0c;系統會自動調用成員對象的無參構造函數。順序上&#xff1a;先調用成員對象的構造函數…

c,c++中字符串處理函數strtok,strstr,strchr,strsub

http://blog.csdn.net/wangqing_12345/article/details/51760220 1&#xff0c;字符串切割函數 函數原型&#xff1a;char *strtok(char *s, char *delim); 函數功能&#xff1a;把字符串s按照字符串delim進行分割&#xff0c;然后返回分割的結果。 函數使用說&#xff1a; 1…

C++虛基類成員可見性

詳見《CPrimer》[第五版]719頁 如果繼承路徑上沒有和虛基類成員重名的成員&#xff0c;則不存在二義性&#xff0c;因為我們僅能訪問到虛基類成員。 當訪問僅有一條繼承路徑上含有和虛基類成員重名的成員&#xff0c;也不存在二義性。派生類的成員的優先級比基類的成員高&…

鏈表逆序的原理及實例

http://blog.csdn.net/wangqing_12345/article/details/51757294 尾插法建立鏈表&#xff0c;帶頭結點設鏈表節點為typedef struct node {int data;struct node *next;}node_t, *pnode_t;要求將一帶鏈表頭List head的單向鏈表逆序。 分析&#xff1a; 1). 若鏈表為空或只有一個…

C++關于虛基類、構造函數、析構函數、成員對象的兩個程序淺析

預備博客&#xff1a; C虛繼承中構造函數和析構函數順序問題以及原理 C派生類含有成員對象構造函數析構函數順序 C虛基類成員可見性 程序一如下&#xff1a; #include<iostream> using namespace std; class A { public:A(int a) :x(a) { cout << "A const…

strtok函數及其實現

頭文件&#xff1a;#include <string.h> 定義函數&#xff1a;char * strtok(char *s, const char *delim); 函數說明&#xff1a;strtok()用來將字符串分割成一個個片段。參數s 指向欲分割的字符串&#xff0c;參數delim 則為分割字符串&#xff0c;當 strtok()在參數s …

C++小型公司管理系統

項目要求&#xff1a; 編寫一個程序實現小型公司的人員信息管理系統。該公司雇員&#xff08;employee&#xff09;包括經理&#xff08;manager&#xff09;&#xff0c;技術人員&#xff08;technician&#xff09;、銷售員&#xff08;salesman&#xff09;和銷售部經理&…

Linux網絡編程“驚群”問題總結

http://www.cnblogs.com/Anker/p/7071849.html 1、前言 我從事Linux系統下網絡開發將近4年了&#xff0c;經常還是遇到一些問題&#xff0c;只是知其然而不知其所以然&#xff0c;有時候和其他人交流&#xff0c;搞得非常尷尬。如今計算機都是多核了&#xff0c;網絡編程框架也…

【Java學習筆記六】常用數據對象之String

字符串 在Java中系統定義了兩種類型的字符串類&#xff1a;String和StringBuffer String類對象的值和長度都不能改變&#xff0c;稱為常量字符串類&#xff0c;其中每個值稱為常量字符串。 StringBuffer類對象的值和長度都可以改變&#xff0c;稱為變量字符串類&#xff0c;其…

【Java學習筆記七】常用數據對象之數組

同一般的對象創建和定義一樣&#xff0c;數組的定義和創建可以分開進行也可以合并一起進行。 一維數組定義格式&#xff1a; <元素類型>[] <數組名>;//[]也可以放在數組名的后面一維數組創建格式&#xff1a; new <元素類型>[<元素個數>];執行new運…

yfan.qiu linux硬鏈接與軟鏈接

http://www.cnblogs.com/yfanqiu/archive/2012/06/11/2545556.html Linux 系統中有軟鏈接和硬鏈接兩種特殊的“文件”。 軟鏈接可以看作是Windows中的快捷方式&#xff0c;可以讓你快速鏈接到目標檔案或目錄。 硬鏈接則透過文件系統的inode來產生新檔名&#xff0c;而不是產生…

【Java學習筆記八】包裝類和vector

包裝類 在Java語言中&#xff0c;每一種基本的數據類型都有相應的對象類型&#xff0c;稱為他們基本類型的包裝類&#xff08;包裹類&#xff09;。 字節byte&#xff1a;Byte、短整數型short&#xff1a;Short 標準整數型int&#xff1a;Integer、長整數型long&#xff1a;Lo…

Linux C++線程池實例

http://www.cnblogs.com/danxi/p/6636095.html 想做一個多線程服務器測試程序&#xff0c;因此參考了github的一些實例&#xff0c;然后自己動手寫了類似的代碼來加深理解。 目前了解的線程池實現有2種思路&#xff1a; 第一種&#xff1a; 主進程創建一定數量的線程&#xff0…

Java編寫簡單的自定義異常類

除了系統中自己帶的異常&#xff0c;我們也可以自己寫一些簡單的異常類來幫助我們處理問題。 所有的異常命名都是以Exception結尾&#xff0c;并且都是Exception的子類。 假設我們要編寫一個人類的類&#xff0c;為了判斷年齡的輸入是否合法&#xff0c;我們編寫了一個名為Il…

shared_ptr簡介以及常見問題

http://blog.csdn.net/stelalala/article/details/19993425 本文中的shared_ptr以vs2010中的std::tr1::shared_ptr作為研究對象。可能和boost中的有些許差異&#xff0c;特此說明。 基本功能 shared_ptr提供了一個管理內存的簡單有效的方法。shared_ptr能在以下方面給開發提供便…

【Java學習筆記九】多線程

程序&#xff1a;計算機指令的集合&#xff0c;它以文件的形式存儲在磁盤上&#xff0c;是應用程序執行的藍本。 進程&#xff1a;是一個程序在其自身的地址空間中的一次執行活動。進程是資源申請、調度和獨立運行的單位&#xff0c;因此&#xff0c;它使用系統中的運行資源。而…

【C++11新特性】 C++11智能指針之weak_ptr

http://blog.csdn.net/xiejingfa/article/details/50772571 原創作品&#xff0c;轉載請標明&#xff1a;http://blog.csdn.net/Xiejingfa/article/details/50772571 如題&#xff0c;我們今天要講的是C11引入的三種智能指針中的最后一個&#xff1a;weak_ptr。在學習weak_ptr之…