IOCP的程序

C代碼 ?收藏代碼
  1. #include?<winsock2.h>??
  2. #include?<mswsock.h>??
  3. #include?<windows.h>??
  4. #include?<stdio.h>??
  5. #include?<stdlib.h>??
  6. #include?<assert.h>??
  7. #include?"vld.h"??
  8. ??
  9. #pragma?message("automatic?link?to?ws2_32.lib?and?mswsock.lib")??
  10. #pragma?comment(lib,?"ws2_32.lib")??
  11. #pragma?comment(lib,?"mswsock.lib")??
  12. ??
  13. ??
  14. ??
  15. ??
  16. #define?RETURN_SUCESS?(0)??
  17. #define?RETURN_FAILED?(-1)??
  18. ??
  19. #define?PORT?5150//端口??
  20. #define?IOCP_THREAD_MAX?16//最大的線程數??
  21. #define?DATA_BUFSIZE?8192??
  22. ??
  23. ??
  24. ??
  25. //區別是何種完成事件??
  26. enum?IO_EVENT??
  27. {??
  28. ????IO_EVENT_ACCEPT,??
  29. ????IO_EVENT_WSARECV,??
  30. ????IO_EVENT_WSARECVFROM,??
  31. ????//不支持異步發送??
  32. ????//IO_EVENT_WSASEND,??
  33. ????//IO_EVENT_WSASENDTO??
  34. };??
  35. ??
  36. ??
  37. ??
  38. ??
  39. typedef?struct?overlapped_wrapper??
  40. {??
  41. ????//OVERLAPPED要放在第一個??
  42. ????OVERLAPPED?overlapped;??
  43. ????int?io_type;//指示是何種IO操作??
  44. }overlapped_wrapper;??
  45. ??
  46. ??
  47. ??
  48. typedef?struct?acceptex_block??
  49. {??
  50. ????//OVERLAPPED要放在第一個??
  51. ????OVERLAPPED?overlapped;??
  52. ????int?io_type;//指示是何種IO操作??
  53. ??
  54. ????char?buffer[DATA_BUFSIZE];??
  55. ????SOCKET?listen_socket;??
  56. ????SOCKET?accept_socket;??
  57. }acceptex_block;??
  58. ??
  59. ??
  60. ??
  61. typedef?struct?recv_block??
  62. {??
  63. ????//OVERLAPPED要放在第一個??
  64. ????OVERLAPPED?overlapped;??
  65. ????int?io_type;//指示是何種IO操作??
  66. ??
  67. ????char?buffer[DATA_BUFSIZE];??
  68. ????SOCKET?socket;??
  69. ????WSABUF?wsa_recv_buf;??
  70. ????DWORD?bytes_recveived;??
  71. }recv_block;??
  72. ??
  73. ??
  74. ??
  75. typedef?struct?recvfrom_block??
  76. {??
  77. ????//OVERLAPPED要放在第一個??
  78. ????OVERLAPPED?overlapped;??
  79. ????int?io_type;//指示是何種IO操作??
  80. ??
  81. ????char?buffer[DATA_BUFSIZE];??
  82. ????SOCKET?socket;??
  83. ????WSABUF?wsa_recv_buf;??
  84. ????DWORD?bytes_recveived;??
  85. ??
  86. ????//UDP包的源地址??
  87. ????struct?sockaddr_in?from_address;??
  88. ????int?from_address_len;??
  89. }recvfrom_block;??
  90. ??
  91. ??
  92. ??
  93. ??
  94. ??
  95. ??
  96. int?get_cpu_number();??
  97. ??
  98. int?async_AcceptEx(acceptex_block*?block);??
  99. int?async_WSARecv(recv_block*?block);??
  100. int?async_WSARecvFrom(recvfrom_block*?block);??
  101. ??
  102. void?on_acceptex(acceptex_block*?block);??
  103. void?on_recv(recv_block*?block);??
  104. void?on_recvfrom(recvfrom_block*?block);??
  105. void?on_tcp_listen_close(acceptex_block*?block);??
  106. void?on_tcp_close(recv_block*?block);??
  107. void?on_udp_close(recvfrom_block*?block);??
  108. ??
  109. int?init(void);??
  110. void?uninit(void);??
  111. DWORD?WINAPI?worker_thread(LPVOID?CompletionPortID);??
  112. void?exit_error();??
  113. ??
  114. ??
  115. ??
  116. ??
  117. ??
  118. //完成端口的句柄??
  119. HANDLE?g_completion_port?=?INVALID_HANDLE_VALUE;??
  120. //工作線程句柄??
  121. HANDLE?g_threads[IOCP_THREAD_MAX];??
  122. //工作線程數量??
  123. int?g_threads_number?=?0;??
  124. ??
  125. ??
  126. int?main(void)??
  127. {??
  128. ????/************************************************************************/??
  129. ????/*TCP的例子*/??
  130. ????/************************************************************************/??
  131. ????SOCKADDR_IN?internet_address;??
  132. ????SOCKET?listen_socket;??
  133. ????acceptex_block*?block;??
  134. ??
  135. ????if(RETURN_FAILED?==?init())??
  136. ????????exit_error();??
  137. ??
  138. ????if?((listen_socket?=?socket(AF_INET,?SOCK_STREAM,?IPPROTO_TCP))?==?INVALID_SOCKET)??
  139. ????????exit_error();??
  140. ??
  141. ????internet_address.sin_family?=?AF_INET;??
  142. ????internet_address.sin_addr.s_addr?=?htonl(INADDR_ANY);??
  143. ????internet_address.sin_port?=?htons(PORT);??
  144. ??
  145. ????if?(bind(listen_socket,?(PSOCKADDR)?&internet_address,?sizeof(internet_address))?==?SOCKET_ERROR)??
  146. ????????exit_error();??
  147. ??
  148. ????if?(listen(listen_socket,?SOMAXCONN)?==?SOCKET_ERROR)??
  149. ????????exit_error();??
  150. ??
  151. ????printf("listening?socket?%d\n",?PORT);??
  152. ??
  153. ????//把監聽的SOCKET和完成端口綁定??
  154. ????if(NULL?==?CreateIoCompletionPort((HANDLE)listen_socket,?g_completion_port,?(u_long)listen_socket,?0))??
  155. ????????exit_error();??
  156. ??
  157. ????block?=?(acceptex_block*)malloc(sizeof(acceptex_block));??
  158. ????block->listen_socket?=?listen_socket;??
  159. ????async_AcceptEx(block);??
  160. ????getchar();??
  161. ????closesocket(listen_socket);??
  162. ????getchar();??
  163. ????uninit();??
  164. ????return?0;??
  165. ??
  166. ??
  167. ??
  168. ????/************************************************************************/??
  169. ????/*UDP的例子*/??
  170. ????/************************************************************************/??
  171. ????//SOCKADDR_IN?internet_address;??
  172. ????//SOCKET?sock;??
  173. ????//recvfrom_block*?block?=?(recvfrom_block*)malloc(sizeof(recvfrom_block));??
  174. ??
  175. ????//if(RETURN_FAILED?==?init())??
  176. ????//??exit_error();??
  177. ??
  178. ????//if?((sock?=?socket(AF_INET,?SOCK_DGRAM,?IPPROTO_UDP))?==?INVALID_SOCKET)??
  179. ????//??exit_error();??
  180. ??
  181. ????//internet_address.sin_family?=?AF_INET;??
  182. ????//internet_address.sin_addr.s_addr?=?htonl(INADDR_ANY);??
  183. ????//internet_address.sin_port?=?htons(PORT);??
  184. ??
  185. ????//if?(bind(sock,?(PSOCKADDR)?&internet_address,?sizeof(internet_address))?==?SOCKET_ERROR)??
  186. ????//??exit_error();??
  187. ??
  188. ????//if(NULL?==?CreateIoCompletionPort((HANDLE)sock,?g_completion_port,?(u_long)sock,?0))??
  189. ????//??exit_error();??
  190. ??
  191. ????//block->socket?=?sock;??
  192. ????//async_WSARecvFrom(block);??
  193. ??
  194. ??
  195. ????//getchar();??
  196. ????//closesocket(sock);??
  197. ????//getchar();??
  198. ????//uninit();??
  199. ????//return?0;??
  200. }??
  201. ??
  202. ??
  203. ??
  204. ??
  205. int?init(void)??
  206. {??
  207. ????WSADATA?wsa_data;??
  208. ????int?i;??
  209. #if?defined?_DEBUG?||?defined?DEBUG??
  210. ????//調試時用一個線程方便??
  211. ????int?threads?=?1;??
  212. #else??
  213. ????int?threads?=?get_cpu_number();??
  214. #endif??
  215. ??
  216. ??
  217. ????if?(WSAStartup(0x0202,?&wsa_data)?!=?0)??
  218. ????????return?RETURN_FAILED;??
  219. ??
  220. ????//建立完成端口??
  221. ????if?((g_completion_port?=?CreateIoCompletionPort(INVALID_HANDLE_VALUE,?NULL,?0,?0))?==?NULL)??
  222. ????????return?RETURN_FAILED;??
  223. ??
  224. ????if(threads?>?IOCP_THREAD_MAX)??
  225. ????????threads?=?IOCP_THREAD_MAX;??
  226. ????for(i?=?0;?i?<?threads;?i++)??
  227. ????{??
  228. ????????//創建工作線程??
  229. ????????g_threads[g_threads_number++]?=?CreateThread(NULL,?0,?worker_thread,?NULL,?0,?0);??
  230. ????}??
  231. ????return?RETURN_SUCESS;??
  232. }??
  233. ??
  234. ??
  235. ??
  236. void?uninit(void)??
  237. {??
  238. ????//自定義的退出協議,三個參數全為0時退出??
  239. ????PostQueuedCompletionStatus(g_completion_port,?0,?0,?NULL);??
  240. ??
  241. ????WaitForMultipleObjects(g_threads_number,?g_threads,?TRUE,?INFINITE);??
  242. ??
  243. ????CloseHandle(g_completion_port);??
  244. ??
  245. ????WSACleanup();??
  246. }??
  247. ??
  248. ??
  249. int?get_cpu_number()??
  250. {??
  251. ????SYSTEM_INFO?system_info;??
  252. ????GetSystemInfo(&system_info);??
  253. ????return?system_info.dwNumberOfProcessors;??
  254. }??
  255. ??
  256. ??
  257. void?exit_error()??
  258. {??
  259. ????int?error?=?GetLastError();??
  260. ????if?(error?==?0)??
  261. ????{??
  262. ????????exit(RETURN_SUCESS);??
  263. ????}??
  264. ????else??
  265. ????{??
  266. ????????fprintf(stderr,?"error:%d\n",?error);??
  267. ????????exit(RETURN_FAILED);??
  268. ????}??
  269. }??
  270. ??
  271. ??
  272. ??
  273. /*?
  274. 投遞一次AcceptEx請求?
  275. 返回TRUE,成功?
  276. 返回FALSE,失敗,WSAGetLastError()獲取進一步信息?
  277. */??
  278. int?async_AcceptEx(acceptex_block*?block)??
  279. {??
  280. ????DWORD?address_length;??
  281. ????DWORD?bytes_received;??
  282. ??
  283. ????//準備投遞一個異步接受請求??
  284. ????SOCKET?accept_socket?=?socket(AF_INET,?SOCK_STREAM,?IPPROTO_TCP);??
  285. ????if(accept_socket?==?INVALID_SOCKET)??
  286. ????????return?RETURN_FAILED;??
  287. ??
  288. ????block->io_type?=?IO_EVENT_ACCEPT;??
  289. ????block->accept_socket?=?accept_socket;??
  290. ????memset(&block->overlapped,?0,???
  291. ????????sizeof(block->overlapped));??
  292. ??
  293. ??
  294. ????address_length?=?sizeof(struct?sockaddr_in)?+?16;??
  295. ????if(!AcceptEx(??
  296. ????????block->listen_socket,???
  297. ????????accept_socket,??
  298. ????????block->buffer,//這個參數會傳遞給完成端口??
  299. ????????0,//DATA_BUFSIZE?-?i?*?2,???????//傳0進來,接受的連接的時候不接受數據??
  300. ????????address_length,?address_length,??
  301. ????????&bytes_received,???
  302. ????????&block->overlapped))??
  303. ????{??
  304. ????????if(WSAGetLastError()?!=?ERROR_IO_PENDING)??
  305. ????????????goto?fail;??
  306. ????}??
  307. ????return?RETURN_SUCESS;??
  308. ??
  309. fail:??
  310. ????closesocket(accept_socket);??
  311. ????return?RETURN_FAILED;??
  312. }??
  313. ??
  314. ??
  315. ??
  316. ??
  317. ??
  318. ??
  319. ??
  320. ??
  321. /*?
  322. 投遞一次WSARecv請求?
  323. 返回TRUE,表示接受請求投遞成功?
  324. 返回FALSE,表示連接已經斷開,WSAGetLastError()獲取進一步信息?
  325. */??
  326. int?async_WSARecv(recv_block*?block)??
  327. {??
  328. ????int?ret;??
  329. ????DWORD?recv_bytes,?flags?=?0;??
  330. ??
  331. ????block->io_type?=?IO_EVENT_WSARECV;??
  332. ????block->bytes_recveived?=?0;??
  333. ????block->wsa_recv_buf.len?=?DATA_BUFSIZE;??
  334. ????block->wsa_recv_buf.buf?=?block->buffer;??
  335. ????memset(&(block->overlapped),?0,?sizeof(block->overlapped));??
  336. ??
  337. ??
  338. ????//投遞一次接受請求??
  339. ????ret?=?WSARecv(block->socket,?&block->wsa_recv_buf,?1,?&recv_bytes,?&flags,??
  340. ????????&(block->overlapped),?NULL);??
  341. ??
  342. ????if(ret?==?-1?&&?WSAGetLastError()?!=?ERROR_IO_PENDING)??
  343. ????{??
  344. ????????printf("WSARecv()?error?returns?%d\n",?ret);??
  345. ????????on_tcp_close(block);??
  346. ????????return?RETURN_FAILED;??
  347. ????}??
  348. ????else?if((ret?==?0)?||?(ret?==?-1?&&?WSAGetLastError()?==?ERROR_IO_PENDING))??
  349. ????{??
  350. ????????//waiting...?for?next?turn??
  351. ????}??
  352. ????else??
  353. ????{??
  354. ????????//如果直接收到了數據??
  355. ????????block->bytes_recveived?=?ret;??
  356. ????????on_recv(block);??
  357. ????????//遞歸??
  358. ????????return?async_WSARecv(block);??
  359. ????}??
  360. ??
  361. ????return?RETURN_SUCESS;??
  362. }??
  363. ??
  364. ??
  365. ??
  366. ??
  367. ??
  368. /*?
  369. 投遞一次WSARecvFrom請求?
  370. 返回TRUE,表示接受請求投遞成功?
  371. 返回FALSE,表示接受請求投遞失敗,WSAGetLastError()獲取進一步信息?
  372. */??
  373. int?async_WSARecvFrom(recvfrom_block*?block)??
  374. {??
  375. ????int?ret;??
  376. ????DWORD?recv_bytes?=?0,?flags?=?0;??
  377. ??
  378. ????block->io_type?=?IO_EVENT_WSARECVFROM;??
  379. ????block->bytes_recveived?=?0;??
  380. ????block->wsa_recv_buf.len?=?DATA_BUFSIZE;??
  381. ????block->wsa_recv_buf.buf?=?block->buffer;??
  382. ????memset(&block->from_address,?0,?sizeof(block->from_address));??
  383. ????block->from_address_len?=?sizeof(block->from_address);??
  384. ????memset(&(block->overlapped),?0,?sizeof(block->overlapped));??
  385. ??
  386. ??
  387. ????//投遞一次接受請求??
  388. ????ret?=?WSARecvFrom(block->socket,?&block->wsa_recv_buf,?1,?&recv_bytes,?&flags,??
  389. ????????(struct?sockaddr*)&block->from_address,?&block->from_address_len,??
  390. ????????&(block->overlapped),?NULL);??
  391. ??
  392. ????if(ret?==?-1?&&?WSAGetLastError()?!=?ERROR_IO_PENDING)??
  393. ????{??
  394. ????????printf("WSARecvFrom()?error?returns?%d?%d\n",?ret,?WSAGetLastError());??
  395. ????????on_udp_close(block);??
  396. ????????return?RETURN_FAILED;??
  397. ????}??
  398. ????else?if((ret?==?0)?||?(ret?==?-1?&&?WSAGetLastError()?==?ERROR_IO_PENDING))??
  399. ????{??
  400. ????????//waiting...?for?next?turn??
  401. ????}??
  402. ????else??
  403. ????{??
  404. ????????//如果直接收到了數據??
  405. ????????block->bytes_recveived?=?ret;??
  406. ????????on_recvfrom(block);??
  407. ????????//遞歸??
  408. ????????return?async_WSARecvFrom(block);??
  409. ????}??
  410. ??
  411. ????return?RETURN_SUCESS;??
  412. }??
  413. ??
  414. ??
  415. void?on_acceptex(acceptex_block*?block)??
  416. {??
  417. ????DWORD?i;??
  418. ????struct?sockaddr?*p_local_addr;??
  419. ????int?local_addr_len?=?sizeof(struct?sockaddr_in);??
  420. ????struct?sockaddr?*p_remote_addr;??
  421. ????int?remote_addr_len?=?sizeof(struct?sockaddr_in);??
  422. ????struct?sockaddr_in?*p_v4_addr;??
  423. ??
  424. ????recv_block*?r_block;??
  425. ??
  426. ??
  427. ????printf("on_acceptex?%d\n",?block->accept_socket);??
  428. ??
  429. ????i?=?sizeof(struct?sockaddr_in)?+?16;??
  430. ????GetAcceptExSockaddrs(??
  431. ????????block->buffer,??
  432. ????????0,//DATA_BUFSIZE?-?i?*?2,??
  433. ????????i,?i,??
  434. ????????&p_local_addr,??
  435. ????????&local_addr_len,??
  436. ????????&p_remote_addr,??
  437. ????????&remote_addr_len??
  438. ????????);??
  439. ??
  440. ????p_v4_addr?=?(struct?sockaddr_in?*)p_local_addr;??
  441. ????printf("\t本地地址%s:%d\n",???
  442. ????????inet_ntoa(p_v4_addr->sin_addr),?ntohs(p_v4_addr->sin_port));??
  443. ????p_v4_addr?=?(struct?sockaddr_in?*)p_remote_addr;??
  444. ????printf("\t遠程地址%s:%d\n",???
  445. ????????inet_ntoa(p_v4_addr->sin_addr),?ntohs(p_v4_addr->sin_port));??
  446. ??
  447. ??
  448. ??
  449. ????//準備投遞一次WSARecv請求??
  450. ????r_block?=?(recv_block*)malloc(sizeof(recv_block));??
  451. ????r_block->socket?=?block->accept_socket;??
  452. ??
  453. ????//綁定??
  454. ????CreateIoCompletionPort((HANDLE)r_block->socket,???
  455. ????????g_completion_port,?(u_long)r_block->socket,?0);??
  456. ??
  457. ????//投遞一次接受請求??
  458. ????async_WSARecv(r_block);??
  459. ??
  460. ????//繼續投遞AcceptEx請求??
  461. ????async_AcceptEx(block);??
  462. }??
  463. ??
  464. void?on_recv(recv_block*?block)??
  465. {??
  466. ????printf("on_recv?%d,?收到%d?bytes數據\n",?block->socket,?block->bytes_recveived);??
  467. ??
  468. ????async_WSARecv(block);??
  469. }??
  470. ??
  471. ??
  472. void?on_recvfrom(recvfrom_block*?block)??
  473. {??
  474. ????printf("on_recvfrom?%d,?收到%d?bytes數據,?來自%s:%d\n",??
  475. ????????block->socket,??
  476. ????????block->bytes_recveived,??
  477. ????????inet_ntoa(block->from_address.sin_addr),??
  478. ????????ntohs(block->from_address.sin_port));??
  479. ??
  480. ????async_WSARecvFrom(block);??
  481. }??
  482. ??
  483. ??
  484. void?on_tcp_listen_close(acceptex_block*?block)??
  485. {??
  486. ????printf("on_tcp_listen_close?%d\n",?block->accept_socket);??
  487. ????free(block);??
  488. ????closesocket(block->accept_socket);??
  489. }??
  490. ??
  491. ??
  492. void?on_tcp_close(recv_block*?block)??
  493. {??
  494. ????printf("on_tcp_close?%d\n",?block->socket);??
  495. ????free(block);??
  496. ????closesocket(block->socket);??
  497. }??
  498. ??
  499. ??
  500. void?on_udp_close(recvfrom_block*?block)??
  501. {??
  502. ????printf("on_udp_close?%d\n",?block->socket);??
  503. ????free(block);??
  504. ????closesocket(block->socket);??
  505. }??
  506. ??
  507. ??
  508. ??
  509. DWORD?WINAPI?worker_thread(LPVOID?nothing)??
  510. {??
  511. ????DWORD?bytes;??
  512. ????overlapped_wrapper*?over_type;??
  513. ????BOOL?close_socket?=?FALSE;??
  514. ????BOOL?ret;??
  515. ??
  516. ????UNREFERENCED_PARAMETER(nothing);??
  517. ??
  518. ????for(;;)??
  519. ????{??
  520. ????????SOCKET?socket;??
  521. ????????//注意第三個參數,他是CreateIoCompletionPort時傳入的,直接傳入的是一個SOCKET??
  522. ????????//注意第四個參數,他可能是一個recv_block或acceptex_block結構的指針??
  523. ????????//因為OVERLAPPED是PER_IO_OPERATION_DATA的第一個成員,所以可以安全的進行轉換??
  524. ????????ret?=?GetQueuedCompletionStatus(g_completion_port,?&bytes,??
  525. ????????????(LPDWORD)&socket,?(LPOVERLAPPED?*)?&over_type,?INFINITE);??
  526. ??
  527. ??
  528. ????????if(ret?==?ERROR_SUCCESS)??
  529. ????????{??
  530. ????????????DWORD?last_error?=?GetLastError();??
  531. ??
  532. ????????????if(ERROR_INVALID_HANDLE?==?last_error)??
  533. ????????????{??
  534. ????????????????printf("完成端口被關閉,退出\n");??
  535. ????????????????return?0;??
  536. ????????????}??
  537. ????????????else?if(ERROR_NETNAME_DELETED?==?last_error??
  538. ????????????????||?ERROR_OPERATION_ABORTED?==?last_error)??
  539. ????????????{??
  540. ????????????????printf("socket被關閉?或者?操作被取消\n");??
  541. ????????????????close_socket?=?TRUE;??
  542. ????????????}??
  543. ????????????else??
  544. ????????????{??
  545. ????????????????printf("GetLastError?%d\n",?last_error);??
  546. ????????????????continue;??
  547. ????????????}??
  548. ????????}??
  549. ????????//自定義的退出協議,三個參數全為0時退出(見uninit中的PostQueuedCompletionStatus)??
  550. ????????else?if(bytes?==?0?&&?socket?==?0?&&?over_type?==?NULL)??
  551. ????????{??
  552. ????????????return?0;??
  553. ????????}??
  554. ??
  555. ????????assert(over_type);??
  556. ??
  557. ????????switch(over_type->io_type)??
  558. ????????{??
  559. ????????case?IO_EVENT_ACCEPT:??
  560. ????????????{??
  561. ????????????????acceptex_block*?a_block?=?(acceptex_block*)over_type;??
  562. ??
  563. ????????????????if(close_socket)??
  564. ????????????????{??
  565. ????????????????????on_tcp_listen_close(a_block);??
  566. ????????????????}??
  567. ????????????????else??
  568. ????????????????{??
  569. ????????????????????on_acceptex(a_block);??
  570. ????????????????}??
  571. ????????????}??
  572. ????????????break;??
  573. ??
  574. ????????case?IO_EVENT_WSARECV:??
  575. ????????????{??
  576. ????????????????recv_block*?r_block?=?(recv_block*)over_type;??
  577. ????????????????//連接斷開??
  578. ????????????????if?(close_socket?||?bytes?==?0?||?bytes?==?-1)??
  579. ????????????????{??
  580. ????????????????????//測試一下,確定對方肯定關閉連接了??
  581. ????????????????????char?test_close;??
  582. ????????????????????int?r?=?recv(r_block->socket,?&test_close,?sizeof(test_close),?MSG_PEEK);??
  583. ????????????????????if(r?==?0?||?r?==?-1)??
  584. ????????????????????{??
  585. ????????????????????????on_tcp_close(r_block);??
  586. ????????????????????}??
  587. ????????????????}??
  588. ????????????????//收到了bytes字節的數據??
  589. ????????????????else??
  590. ????????????????{??
  591. ????????????????????//處理數據??
  592. ????????????????????r_block->bytes_recveived?=?bytes;??
  593. ????????????????????on_recv(r_block);??
  594. ????????????????}??
  595. ????????????}??
  596. ????????????break;??
  597. ??
  598. ??
  599. ????????case?IO_EVENT_WSARECVFROM:??
  600. ????????????{??
  601. ????????????????recvfrom_block*?rf_block?=?(recvfrom_block*)over_type;??
  602. ??
  603. ????????????????if(close_socket?||?bytes?==?-1?||?bytes?==?0)??
  604. ????????????????{??
  605. ????????????????????on_udp_close(rf_block);??
  606. ????????????????}??
  607. ????????????????else??
  608. ????????????????{??
  609. ????????????????????//處理數據??
  610. ????????????????????rf_block->bytes_recveived?=?bytes;??
  611. ????????????????????on_recvfrom(rf_block);??
  612. ????????????????}??
  613. ????????????}??
  614. ????????????break;??
  615. ??
  616. ??
  617. ????????default:??
  618. ????????????break;??
  619. ????????}??
  620. ????}??
  621. ????return?0;??
  622. }?

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

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

相關文章

PaperNotes(3)-圖像分割-RCNN-FCN-Boxsup

圖像分割算法對比小結1.{基本概念}2.{R-CNN}2.1R-CNN 網絡結構選擇性搜索算法為什么選擇SVM作分類器邊框回歸2.2{R-CNN 訓練}2.3{R-CNN實驗結果}2.4{R-CNN語義分割}2.5{補充材料}2.5.1{R-CNN建議區域放縮}2.5.2{IOU閾值設置不一樣的原因}2.5.3{Bounding-box回歸修正}2.6{R-CNN存…

Python模塊(3)--PIL 簡易使用教程

PIL模塊-用與記1.圖片導入Image.open()2.圖像顯示.show()4.查看圖片屬性.format,.size,.mode3.圖像格式轉換.convert()4.圖像模式“L”&#xff0c;“RGB”,"CYMK"5. 圖片旋轉.rotate()旋轉方式1&#xff1a;旋轉不擴展旋轉方式2&#xff1a;旋轉擴展旋轉方式3&#…

日志級別 debug info warn eirror fatal

日志級別 debug info warn eirror fatal 軟件中總免不了要使用諸如 Log4net, Log4j, Tracer 等東東來寫日志&#xff0c;不管用什么&#xff0c;這些東東大多是大同小異的&#xff0c;一般都提供了這樣5個日志級別&#xff1a; Debug Info Warn Error Fatal一個等級比一個高&…

輸入輸出系統

I/O設備&#xff1a;輸入輸出和存儲功能的設備 I/O設備的分類 按傳輸的速度&#xff1a; 低速設備&#xff08;如鍵盤、鼠標、語音輸入輸出設備&#xff09; 中速設備&#xff08;如行式打印機、激光打印機等&#xff09; 高速設備&#xff08;如磁帶機、磁盤機、光盤機等&…

vue2源碼解析---v-model雙向數據綁定

什么是v-model v-model 是 Vue 中的一個指令&#xff0c;用于實現表單元素與 Vue 實例中數據的雙向綁定。這意味著當表單元素的值發生變化時&#xff0c;Vue 實例中的數據也會隨之更新 工作原理 生成ast樹 本質上是語法糖 結合了v-bind和v-on兩個指令 示例代碼 new Vue({e…

php收集的精典代碼

1. οncοntextmenu"window.event.return&#xff06;#118aluefalse" 將徹底屏蔽鼠標右鍵 <table border οncοntextmenureturn(false)><td>no</table> 可用于Table 2. <body onselectstart"return false"> 取消選取、防止復制…

python外卷(7)--glob

glob模塊1.glob.glob()2.對比os.listdir()glob是python自帶的一個操作文件的模塊&#xff0c;可用于查找 指定路徑 中 匹配的 文件。1.glob.glob() 下面是一個測試文件路徑&#xff1a; (base) pppp-System-Product-Name:~/Desktop/test_glob$ tree . ├── a │ ├── 1…

Sublime Text 2配置強大的IDE開發環境,運行java

Sublime Text 2是我無意中發現的、據說十分強大的、便捷的編輯器&#xff0c;許多程序員都投入到Sublime Text 2的懷抱中。 1 配置java開發環境的方法如下&#xff1a; 在jdk安裝目錄下的bin文件夾下新建一個bat格式的文件&#xff0c;文件命為javacexec.bat。 如果是在Wind…

thinkphp的快捷方法實例化對象

D、F、S、C、L、A、I 他們都在functions.php這個文件家 下面我分別說明一下他們的功能 D&#xff08;&#xff09; 加載Model類 M&#xff08;&#xff09; 加載Model類 A&#xff08;&#xff09; 加載Action類 L&#xff08;&#xff09; 獲取語言定義 C&#xff08;&#xf…

Python外卷(8)--pdist, squareform

pdist, squareform1.pdist, squareform使用例子2.通過矩陣的四則運算實現上述pdist, squareformscipy.spatial.distance 距離計算庫中有兩個函數&#xff1a;pdist, squareform&#xff0c;用于計算樣本對之間的歐式距離&#xff0c;并且將樣本間距離用方陣表示出來。&#xff…

模擬進程調度

功能 data.h #ifndef _Data_h_ #define _Data_h_#include <stdio.h> #include <stdlib.h> #include <string.h>#define ElemType PCB #define Status int #define OK 1 #define ERROR 0 #define TimeSlice 1 #define Infinity 10 //INT_MAX#define NAME_M…

gdb調試多進程和多線程命令

1. 默認設置下&#xff0c;在調試多進程程序時GDB只會調試主進程。但是GDB&#xff08;>V7.0&#xff09;支持多進程的 分別以及同時 調試&#xff0c;換句話說&#xff0c;GDB可以同時調試多個程序。只需要設置follow-fork-mode(默認值&#xff1a;parent)和detach-on-fork…

python外卷(10)--取整

"取整"那些事1.python 內置函數1.1int()--向下取整1.2round()--四舍五入2.math模塊取整函數2.1 math.floor()--向下取整2.2 math.ceil()--向上取整2.3 math.modf()--分別取小數部分和整數部分3.numpy模塊取整函數3.1 numpy.floor()--向下取整3.2 numpy.ceil()--向上取…

模擬銀行家算法

介紹 data.h #ifndef _Data_h_ #define _Data_h_#include <stdio.h> #include <stdlib.h> #include <string.h>#define ElemType PCB #define Status int #define true 1 #define false 0 #define OK 1 #define ERROR 0 #define RESOURCE_NUM …

Lua 與 C混合編程 .

本文通過程序實例說明C調用lua腳本和lua調用C的方法: 先建立一個 test.c文件: #include <stdio.h> #include <stdlib.h> #include "lua.h" #include "lualib.h" #include "lauxlib.h" #pragma comment(lib, "lua5.1.lib&qu…

模擬固定分區分配

介紹 data.h #ifndef _Data_h_ #define _Data_h_#include <stdio.h> #include <stdlib.h> #include <string.h> #define LIST_INIT_SIZE 10 #define LISTINCREMENT 2 #define true 1 #define false 0 #define PCBType PCB #define Status int…

Linux下的lua和boost c++的搭建和安裝

先下載lua &#xff0c;boost c http://www.lua.org/versions.html#5.2 http://www.boost.org/ http://sourceforge.net/projects/luabind/ 1. 安裝lua [rootlocalhost ~]#tar zxvf lua-5.1.2.tar.gz -C /usr/local [rootlocalhost ~]# cd /usr/local/ [rootlocalhost lo…

模擬基本分頁存儲

介紹 data.h #ifndef _Data_h_ #define _Data_h_#include <stdio.h> #include <stdlib.h> #include <string.h> #include <math.h>#define LIST_INIT_SIZE 10 #define LISTINCREMENT 2 #define true 1 #define false 0 #define PCBType PC…

常用正則表達式和shell命令列表

取當前目錄下普通文件的后綴名列表&#xff1a; ls -l | awk /^-/{print $NF} |awk -F. {print $NF}|awk !/^$/ 匹配0和正整數的正則表達式&#xff08;除0以外&#xff0c;其它數字不能以0開頭&#xff09;&#xff1a; (^0$)|(^[0-9]\d*$) 匹配中文字符的正則表達式&#xff…

無限踩坑系列(7)-Latex使用Tips

Latex常用命令1.latex注釋2.圖片左邊對齊3.字母頭上加聲調4.腳注5.公式中加空格6.字體加粗體7.公式換行8.\textsuperscript{*}9.\begin{itemize}10.\operatorname{trace}11.\noindent12.\textcircled{}圓圈數字一些TIPs1.latex注釋 單行使用百分號%注釋 多行使用如下命令,在編…