SocketHelper.cpp 17 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700
  1. /*
  2. * Copyright: JessMA Open Source (ldcsaa@gmail.com)
  3. *
  4. * Version : 3.6.1
  5. * Author : Bruce Liang
  6. * Website : http://www.jessma.org
  7. * Project : https://github.com/ldcsaa
  8. * Blog : http://www.cnblogs.com/ldcsaa
  9. * Wiki : http://www.oschina.net/p/hp-socket
  10. * QQ Group : 75375912
  11. *
  12. * Licensed under the Apache License, Version 2.0 (the "License");
  13. * you may not use this file except in compliance with the License.
  14. * You may obtain a copy of the License at
  15. *
  16. * http://www.apache.org/licenses/LICENSE-2.0
  17. *
  18. * Unless required by applicable law or agreed to in writing, software
  19. * distributed under the License is distributed on an "AS IS" BASIS,
  20. * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  21. * See the License for the specific language governing permissions and
  22. * limitations under the License.
  23. */
  24. #include "stdafx.h"
  25. #include "../../Common/Src/GeneralHelper.h"
  26. #include "../../Common/Src/SysHelper.h"
  27. #include "SocketHelper.h"
  28. #include <mstcpip.h>
  29. #pragma comment(lib, "ws2_32")
  30. ///////////////////////////////////////////////////////////////////////////////////////////////////////
  31. const DWORD MAX_WORKER_THREAD_COUNT = 500;
  32. const DWORD MIN_SOCKET_BUFFER_SIZE = 64;
  33. const DWORD MAX_SMALL_FILE_SIZE = 0x3FFFFF;
  34. const DWORD MAX_CONNECTION_PERIOD = MAXLONG / 2;
  35. const DWORD DEFAULT_MAX_CONNECTION_COUNT = 10000;
  36. const DWORD DEFAULT_WORKER_THREAD_COUNT = min((::SysGetNumberOfProcessors() * 2 + 2), MAX_WORKER_THREAD_COUNT);
  37. const DWORD DEFAULT_FREE_SOCKETOBJ_LOCK_TIME = 10 * 1000;
  38. const DWORD DEFAULT_FREE_SOCKETOBJ_POOL = 150;
  39. const DWORD DEFAULT_FREE_SOCKETOBJ_HOLD = 600;
  40. const DWORD DEFAULT_FREE_BUFFEROBJ_POOL = 300;
  41. const DWORD DEFAULT_FREE_BUFFEROBJ_HOLD = 1200;
  42. const DWORD DEFAULT_CLIENT_FREE_BUFFER_POOL_SIZE = 10;
  43. const DWORD DEFAULT_CLIENT_FREE_BUFFER_POOL_HOLD = 40;
  44. const DWORD DEFAULT_TCP_SOCKET_BUFFER_SIZE = ::SysGetPageSize();
  45. const DWORD DEFALUT_TCP_KEEPALIVE_TIME = 30 * 1000;
  46. const DWORD DEFALUT_TCP_KEEPALIVE_INTERVAL = 10 * 1000;
  47. const DWORD DEFAULT_TCP_SERVER_SOCKET_LISTEN_QUEUE = SOMAXCONN;
  48. const DWORD DEFAULT_TCP_SERVER_ACCEPT_SOCKET_COUNT = 300;
  49. const DWORD DEFAULT_UDP_MAX_DATAGRAM_SIZE = 1472;
  50. const DWORD DEFAULT_UDP_POST_RECEIVE_COUNT = 300;
  51. const DWORD DEFAULT_UDP_DETECT_ATTEMPTS = 3;
  52. const DWORD DEFAULT_UDP_DETECT_INTERVAL = 20;
  53. LPCTSTR DEFAULT_BIND_ADDRESS = _T("0.0.0.0");
  54. const DWORD TCP_PACK_LENGTH_BITS = 22;
  55. const DWORD TCP_PACK_LENGTH_MASK = 0x3FFFFF;
  56. const DWORD TCP_PACK_MAX_SIZE_LIMIT = 0x3FFFFF;
  57. const DWORD TCP_PACK_DEFAULT_MAX_SIZE = 0x040000;
  58. const USHORT TCP_PACK_HEADER_FLAG_LIMIT = 0x0003FF;
  59. const USHORT TCP_PACK_DEFAULT_HEADER_FLAG = 0x000000;
  60. ///////////////////////////////////////////////////////////////////////////////////////////////////////
  61. ULONG GetIPv4InAddr(LPCTSTR lpszAddress)
  62. {
  63. if (!lpszAddress || lpszAddress[0] == '\0')
  64. return INADDR_NONE;
  65. #if _WIN32_WINNT >= _WIN32_WINNT_VISTA
  66. IN_ADDR addr;
  67. if (::InetPton(AF_INET, lpszAddress, &addr.s_addr) == 1)
  68. return addr.s_addr;
  69. return INADDR_NONE;
  70. #else
  71. return ::inet_addr(CT2A(lpszAddress));
  72. #endif
  73. }
  74. BOOL IsIPAddress(LPCTSTR lpszAddress)
  75. {
  76. return GetIPv4InAddr(lpszAddress) != INADDR_NONE;
  77. }
  78. BOOL GetIPAddress(LPCTSTR lpszHost, LPTSTR lpszIP, int& iIPLen)
  79. {
  80. BOOL isOK = TRUE;
  81. if(IsIPAddress(lpszHost))
  82. {
  83. int iHostLen = lstrlen(lpszHost);
  84. if(iHostLen > 0)
  85. ++iHostLen;
  86. if(iHostLen > 0 && iIPLen >= iHostLen)
  87. lstrcpy(lpszIP, lpszHost);
  88. else
  89. isOK = FALSE;
  90. iIPLen = iHostLen;
  91. }
  92. else
  93. {
  94. IN_ADDR addr;
  95. if(GetOptimalIPByHostName(lpszHost, addr))
  96. isOK = IN_ADDR_2_IP(addr, lpszIP, iIPLen);
  97. else
  98. isOK = FALSE;
  99. }
  100. return isOK;
  101. }
  102. BOOL GetOptimalIPByHostName(LPCTSTR lpszHost, IN_ADDR& addr)
  103. {
  104. addr.s_addr = 0;
  105. addrinfo* pInfo = nullptr;
  106. addrinfo hints = {0};
  107. hints.ai_flags = AI_ALL;
  108. hints.ai_family = AF_INET;
  109. int rs = ::getaddrinfo((CT2A)lpszHost, nullptr, &hints, &pInfo);
  110. if(rs == NO_ERROR)
  111. {
  112. IN_ADDR inAddr;
  113. ULONG addrs[3] = {0};
  114. char** pptr = nullptr;
  115. for(addrinfo* pCur = pInfo; pCur != nullptr; pCur = pCur->ai_next)
  116. {
  117. if(pCur->ai_family == AF_INET)
  118. {
  119. inAddr = ((SOCKADDR_IN*)(pCur->ai_addr))->sin_addr;
  120. UCHAR a = inAddr.s_net;
  121. UCHAR b = inAddr.s_host;
  122. if(addrs[0] == 0 && a == 127)
  123. {
  124. addrs[0] = inAddr.s_addr;
  125. break;
  126. }
  127. else if( addrs[1] == 0 &&
  128. (
  129. (a == 10) ||
  130. (a == 172 && b >= 16 && b <= 31) ||
  131. (a == 192 && b == 168)
  132. )
  133. )
  134. addrs[1] = inAddr.s_addr;
  135. else if(addrs[2] == 0)
  136. addrs[2] = inAddr.s_addr;
  137. }
  138. }
  139. ::freeaddrinfo(pInfo);
  140. for(int i = 0; i < 3; i++)
  141. {
  142. if(addrs[i] != 0)
  143. {
  144. addr.s_addr = addrs[i];
  145. break;
  146. }
  147. }
  148. }
  149. return addr.s_addr != 0;
  150. }
  151. BOOL IN_ADDR_2_IP(const IN_ADDR& addr, LPTSTR lpszAddress, int& iAddressLen)
  152. {
  153. BOOL isOK = TRUE;
  154. TCHAR szAddr[16];
  155. wsprintf(szAddr, _T("%hu.%hu.%hu.%hu"), addr.s_net, addr.s_host, addr.s_lh, addr.s_impno);
  156. int iIPLen = lstrlen(szAddr) + 1;
  157. if(iAddressLen >= iIPLen)
  158. memcpy(lpszAddress, szAddr, iIPLen * sizeof(TCHAR));
  159. else
  160. isOK = FALSE;
  161. iAddressLen = iIPLen;
  162. return isOK;
  163. }
  164. BOOL sockaddr_IN_2_A(const SOCKADDR_IN& addr, ADDRESS_FAMILY& usFamily, LPTSTR lpszAddress, int& iAddressLen, USHORT& usPort)
  165. {
  166. usFamily = addr.sin_family;
  167. usPort = ntohs(addr.sin_port);
  168. return IN_ADDR_2_IP(addr.sin_addr, lpszAddress, iAddressLen);
  169. }
  170. BOOL sockaddr_A_2_IN(ADDRESS_FAMILY usFamily, LPCTSTR lpszAddress, USHORT usPort, SOCKADDR_IN& addr)
  171. {
  172. ASSERT(usFamily == AF_INET);
  173. addr.sin_family = usFamily;
  174. addr.sin_port = htons(usPort);
  175. addr.sin_addr.s_addr = GetIPv4InAddr(lpszAddress);
  176. return addr.sin_addr.s_addr != INADDR_NONE;
  177. }
  178. BOOL GetSocketAddress(SOCKET socket, LPTSTR lpszAddress, int& iAddressLen, USHORT& usPort, BOOL bLocal)
  179. {
  180. sockaddr addr;
  181. int addr_len = sizeof(addr);
  182. int result = bLocal ? getsockname(socket, &addr, &addr_len) : getpeername(socket, &addr, &addr_len);
  183. if(result == NO_ERROR)
  184. {
  185. ADDRESS_FAMILY usFamily;
  186. return sockaddr_IN_2_A((sockaddr_in&)addr, usFamily, lpszAddress, iAddressLen, usPort);
  187. }
  188. return FALSE;
  189. }
  190. BOOL GetSocketLocalAddress(SOCKET socket, LPTSTR lpszAddress, int& iAddressLen, USHORT& usPort)
  191. {
  192. return GetSocketAddress(socket, lpszAddress, iAddressLen, usPort, TRUE);
  193. }
  194. BOOL GetSocketRemoteAddress(SOCKET socket, LPTSTR lpszAddress, int& iAddressLen, USHORT& usPort)
  195. {
  196. return GetSocketAddress(socket, lpszAddress, iAddressLen, usPort, FALSE);
  197. }
  198. PVOID GetExtensionFuncPtr(SOCKET sock, GUID guid)
  199. {
  200. DWORD dwBytes;
  201. PVOID pfn = nullptr;
  202. ::WSAIoctl (
  203. sock,
  204. SIO_GET_EXTENSION_FUNCTION_POINTER,
  205. &guid,
  206. sizeof(guid),
  207. &pfn,
  208. sizeof(pfn),
  209. &dwBytes,
  210. nullptr,
  211. nullptr
  212. );
  213. return pfn;
  214. }
  215. LPFN_ACCEPTEX Get_AcceptEx_FuncPtr(SOCKET sock)
  216. {
  217. GUID guid = WSAID_ACCEPTEX;
  218. return (LPFN_ACCEPTEX)GetExtensionFuncPtr(sock, guid);
  219. }
  220. LPFN_GETACCEPTEXSOCKADDRS Get_GetAcceptExSockaddrs_FuncPtr(SOCKET sock)
  221. {
  222. GUID guid = WSAID_GETACCEPTEXSOCKADDRS;
  223. return (LPFN_GETACCEPTEXSOCKADDRS)GetExtensionFuncPtr(sock, guid);
  224. }
  225. LPFN_CONNECTEX Get_ConnectEx_FuncPtr(SOCKET sock)
  226. {
  227. GUID guid = WSAID_CONNECTEX;
  228. return (LPFN_CONNECTEX)GetExtensionFuncPtr(sock, guid);
  229. }
  230. LPFN_TRANSMITFILE Get_TransmitFile_FuncPtr(SOCKET sock)
  231. {
  232. GUID guid = WSAID_TRANSMITFILE;
  233. return (LPFN_TRANSMITFILE)GetExtensionFuncPtr(sock, guid);
  234. }
  235. LPFN_DISCONNECTEX Get_DisconnectEx_FuncPtr (SOCKET sock)
  236. {
  237. GUID guid = WSAID_DISCONNECTEX;
  238. return (LPFN_DISCONNECTEX)GetExtensionFuncPtr(sock, guid);
  239. }
  240. ///////////////////////////////////////////////////////////////////////////////////////////////////////
  241. BOOL PostIocpCommand(HANDLE hIOCP, EnIocpCommand enCmd, ULONG_PTR ulParam)
  242. {
  243. return ::PostQueuedCompletionStatus(hIOCP, enCmd, ulParam, nullptr);
  244. }
  245. BOOL PostIocpExit(HANDLE hIOCP)
  246. {
  247. return ::PostQueuedCompletionStatus(hIOCP, IOCP_CMD_EXIT, 0, nullptr);
  248. }
  249. BOOL PostIocpAccept(HANDLE hIOCP)
  250. {
  251. return ::PostQueuedCompletionStatus(hIOCP, IOCP_CMD_ACCEPT, 0, nullptr);
  252. }
  253. BOOL PostIocpDisconnect(HANDLE hIOCP, CONNID dwConnID)
  254. {
  255. return ::PostQueuedCompletionStatus(hIOCP, IOCP_CMD_DISCONNECT, dwConnID, nullptr);
  256. }
  257. BOOL PostIocpSend(HANDLE hIOCP, CONNID dwConnID)
  258. {
  259. return ::PostQueuedCompletionStatus(hIOCP, IOCP_CMD_SEND, dwConnID, nullptr);
  260. }
  261. ///////////////////////////////////////////////////////////////////////////////////////////////////////
  262. int SSO_SetSocketOption(SOCKET sock, int level, int name, LPVOID val, int len)
  263. {
  264. return setsockopt(sock, level, name, (CHAR*)val, len);
  265. }
  266. int SSO_GetSocketOption(SOCKET sock, int level, int name, LPVOID val, int* len)
  267. {
  268. return getsockopt(sock, level, name, (CHAR*)val, len);
  269. }
  270. int SSO_IoctlSocket(SOCKET sock, long cmd, u_long* arg)
  271. {
  272. return ioctlsocket(sock, cmd, arg);
  273. }
  274. int SSO_WSAIoctl(SOCKET sock, DWORD dwIoControlCode, LPVOID lpvInBuffer, DWORD cbInBuffer, LPVOID lpvOutBuffer, DWORD cbOutBuffer, LPDWORD lpcbBytesReturned)
  275. {
  276. return ::WSAIoctl(sock, dwIoControlCode, lpvInBuffer, cbInBuffer, lpvOutBuffer, cbOutBuffer, lpcbBytesReturned, nullptr, nullptr);
  277. }
  278. int SSO_UpdateAcceptContext(SOCKET soClient, SOCKET soBind)
  279. {
  280. return setsockopt(soClient, SOL_SOCKET, SO_UPDATE_ACCEPT_CONTEXT, (CHAR*)&soBind, sizeof(SOCKET));
  281. }
  282. int SSO_UpdateConnectContext(SOCKET soClient, int iOption)
  283. {
  284. return setsockopt(soClient, SOL_SOCKET, SO_UPDATE_CONNECT_CONTEXT, (CHAR*)&iOption, sizeof(int));
  285. }
  286. int SSO_NoDelay(SOCKET sock, BOOL bNoDelay)
  287. {
  288. return setsockopt(sock, IPPROTO_TCP, TCP_NODELAY, (CHAR*)&bNoDelay, sizeof(BOOL));
  289. }
  290. int SSO_DontLinger(SOCKET sock, BOOL bDont)
  291. {
  292. return setsockopt(sock, SOL_SOCKET, SO_DONTLINGER, (CHAR*)&bDont, sizeof(BOOL));
  293. }
  294. int SSO_Linger(SOCKET sock, USHORT l_onoff, USHORT l_linger)
  295. {
  296. linger ln = {l_onoff, l_linger};
  297. return setsockopt(sock, SOL_SOCKET, SO_LINGER, (CHAR*)&ln, sizeof(linger));
  298. }
  299. int SSO_KeepAlive(SOCKET sock, BOOL bKeepAlive)
  300. {
  301. return setsockopt(sock, SOL_SOCKET, SO_KEEPALIVE, (CHAR*)&bKeepAlive, sizeof(BOOL));
  302. }
  303. int SSO_KeepAliveVals(SOCKET sock, u_long onoff, u_long time, u_long interval)
  304. {
  305. int result = NO_ERROR;
  306. tcp_keepalive in = {onoff, time, interval};
  307. DWORD dwBytes;
  308. if(::WSAIoctl (
  309. sock,
  310. SIO_KEEPALIVE_VALS,
  311. (LPVOID)&in,
  312. sizeof(in),
  313. nullptr,
  314. 0,
  315. &dwBytes,
  316. nullptr,
  317. nullptr
  318. ) == SOCKET_ERROR)
  319. {
  320. result = ::WSAGetLastError();
  321. if(result == WSAEWOULDBLOCK)
  322. result = NO_ERROR;
  323. }
  324. return result;
  325. }
  326. int SSO_RecvBuffSize(SOCKET sock, int size)
  327. {
  328. return setsockopt(sock, SOL_SOCKET, SO_RCVBUF, (CHAR*)&size, sizeof(int));
  329. }
  330. int SSO_SendBuffSize(SOCKET sock, int size)
  331. {
  332. return setsockopt(sock, SOL_SOCKET, SO_SNDBUF, (CHAR*)&size, sizeof(int));
  333. }
  334. int SSO_ReuseAddress(SOCKET sock, BOOL bReuse)
  335. {
  336. return setsockopt(sock, SOL_SOCKET, SO_REUSEADDR, (CHAR*)&bReuse, sizeof(BOOL));
  337. }
  338. int SSO_UDP_ConnReset(SOCKET sock, BOOL bNewBehavior)
  339. {
  340. int result = NO_ERROR;
  341. DWORD dwBytes;
  342. if(::WSAIoctl (
  343. sock,
  344. SIO_UDP_CONNRESET,
  345. (LPVOID)&bNewBehavior,
  346. sizeof(bNewBehavior),
  347. nullptr,
  348. 0,
  349. &dwBytes,
  350. nullptr,
  351. nullptr
  352. ) == SOCKET_ERROR)
  353. {
  354. result = ::WSAGetLastError();
  355. if(result == WSAEWOULDBLOCK)
  356. result = NO_ERROR;
  357. }
  358. return result;
  359. }
  360. ///////////////////////////////////////////////////////////////////////////////////////////////////////
  361. CONNID GenerateConnectionID()
  362. {
  363. static volatile CONNID s_dwConnID = 0;
  364. CONNID dwConnID = ::InterlockedIncrement(&s_dwConnID);
  365. if(dwConnID == 0)
  366. dwConnID = ::InterlockedIncrement(&s_dwConnID);
  367. return dwConnID;
  368. }
  369. int ManualCloseSocket(SOCKET sock, int iShutdownFlag, BOOL bGraceful, BOOL bReuseAddress)
  370. {
  371. if(!bGraceful)
  372. SSO_Linger(sock, 1, 0);
  373. if(bReuseAddress)
  374. SSO_ReuseAddress(sock, bReuseAddress);
  375. if(iShutdownFlag != 0xFF)
  376. shutdown(sock, iShutdownFlag);
  377. return closesocket(sock);
  378. }
  379. int PostAccept(LPFN_ACCEPTEX pfnAcceptEx, SOCKET soListen, SOCKET soClient, TBufferObj* pBufferObj)
  380. {
  381. int result = PostAcceptNotCheck(pfnAcceptEx, soListen, soClient, pBufferObj);
  382. if(result == WSA_IO_PENDING)
  383. result = NO_ERROR;
  384. return result;
  385. }
  386. int PostAcceptNotCheck(LPFN_ACCEPTEX pfnAcceptEx, SOCKET soListen, SOCKET soClient, TBufferObj* pBufferObj)
  387. {
  388. int result = NO_ERROR;
  389. pBufferObj->client = soClient;
  390. pBufferObj->operation = SO_ACCEPT;
  391. if(!pfnAcceptEx (
  392. soListen,
  393. pBufferObj->client,
  394. pBufferObj->buff.buf,
  395. 0,
  396. sizeof(SOCKADDR_IN) + 16,
  397. sizeof(SOCKADDR_IN) + 16,
  398. nullptr,
  399. &pBufferObj->ov
  400. )
  401. )
  402. {
  403. result = ::WSAGetLastError();
  404. }
  405. return result;
  406. }
  407. int PostConnect(LPFN_CONNECTEX pfnConnectEx, SOCKET soClient, SOCKADDR_IN& soAddrIN, TBufferObj* pBufferObj)
  408. {
  409. int result = PostConnectNotCheck(pfnConnectEx, soClient, soAddrIN, pBufferObj);
  410. if(result == WSA_IO_PENDING)
  411. result = NO_ERROR;
  412. return result;
  413. }
  414. int PostConnectNotCheck(LPFN_CONNECTEX pfnConnectEx, SOCKET soClient, SOCKADDR_IN& soAddrIN, TBufferObj* pBufferObj)
  415. {
  416. int result = NO_ERROR;
  417. pBufferObj->client = soClient;
  418. pBufferObj->operation = SO_CONNECT;
  419. if(!pfnConnectEx (
  420. soClient,
  421. (SOCKADDR*)&soAddrIN,
  422. sizeof(SOCKADDR_IN),
  423. nullptr,
  424. 0,
  425. nullptr,
  426. &pBufferObj->ov
  427. )
  428. )
  429. {
  430. result = ::WSAGetLastError();
  431. }
  432. return result;
  433. }
  434. int PostSend(TSocketObj* pSocketObj, TBufferObj* pBufferObj)
  435. {
  436. int result = PostSendNotCheck(pSocketObj, pBufferObj);
  437. if(result == WSA_IO_PENDING)
  438. result = NO_ERROR;
  439. return result;
  440. }
  441. int PostSendNotCheck(TSocketObj* pSocketObj, TBufferObj* pBufferObj)
  442. {
  443. int result = NO_ERROR;
  444. DWORD dwBytes = 0;
  445. pBufferObj->client = pSocketObj->socket;
  446. pBufferObj->operation = SO_SEND;
  447. if(::WSASend(
  448. pBufferObj->client,
  449. &pBufferObj->buff,
  450. 1,
  451. &dwBytes,
  452. 0,
  453. &pBufferObj->ov,
  454. nullptr
  455. ) == SOCKET_ERROR)
  456. {
  457. result = ::WSAGetLastError();
  458. }
  459. return result;
  460. }
  461. int PostReceive(TSocketObj* pSocketObj, TBufferObj* pBufferObj)
  462. {
  463. int result = PostReceiveNotCheck(pSocketObj, pBufferObj);
  464. if(result == WSA_IO_PENDING)
  465. result = NO_ERROR;
  466. return result;
  467. }
  468. int PostReceiveNotCheck(TSocketObj* pSocketObj, TBufferObj* pBufferObj)
  469. {
  470. int result = NO_ERROR;
  471. DWORD dwFlag = 0;
  472. DWORD dwBytes = 0;
  473. pBufferObj->client = pSocketObj->socket;
  474. pBufferObj->operation = SO_RECEIVE;
  475. if(::WSARecv(
  476. pBufferObj->client,
  477. &pBufferObj->buff,
  478. 1,
  479. &dwBytes,
  480. &dwFlag,
  481. &pBufferObj->ov,
  482. nullptr
  483. ) == SOCKET_ERROR)
  484. {
  485. result = ::WSAGetLastError();
  486. }
  487. return result;
  488. }
  489. int PostSendTo(SOCKET sock, TUdpBufferObj* pBufferObj)
  490. {
  491. int result = PostSendToNotCheck(sock, pBufferObj);
  492. if(result == WSA_IO_PENDING)
  493. result = NO_ERROR;
  494. return result;
  495. }
  496. int PostSendToNotCheck(SOCKET sock, TUdpBufferObj* pBufferObj)
  497. {
  498. int result = NO_ERROR;
  499. DWORD dwBytes = 0;
  500. pBufferObj->operation = SO_SEND;
  501. pBufferObj->addrLen = sizeof(SOCKADDR_IN);
  502. if(::WSASendTo (
  503. sock,
  504. &pBufferObj->buff,
  505. 1,
  506. &dwBytes,
  507. 0,
  508. (sockaddr*)&pBufferObj->remoteAddr,
  509. pBufferObj->addrLen,
  510. &pBufferObj->ov,
  511. nullptr
  512. ) == SOCKET_ERROR)
  513. {
  514. result = ::WSAGetLastError();
  515. }
  516. return result;
  517. }
  518. int PostReceiveFrom(SOCKET sock, TUdpBufferObj* pBufferObj)
  519. {
  520. int result = PostReceiveFromNotCheck(sock, pBufferObj);
  521. if(result == WSA_IO_PENDING)
  522. result = NO_ERROR;
  523. return result;
  524. }
  525. int PostReceiveFromNotCheck(SOCKET sock, TUdpBufferObj* pBufferObj)
  526. {
  527. int result = NO_ERROR;
  528. DWORD dwFlag = 0;
  529. DWORD dwBytes = 0;
  530. pBufferObj->operation = SO_RECEIVE;
  531. pBufferObj->addrLen = sizeof(SOCKADDR_IN);
  532. ::ZeroMemory(&pBufferObj->remoteAddr, pBufferObj->addrLen);
  533. if(::WSARecvFrom(
  534. sock,
  535. &pBufferObj->buff,
  536. 1,
  537. &dwBytes,
  538. &dwFlag,
  539. (sockaddr*)&pBufferObj->remoteAddr,
  540. &pBufferObj->addrLen,
  541. &pBufferObj->ov,
  542. nullptr
  543. ) == SOCKET_ERROR)
  544. {
  545. result = ::WSAGetLastError();
  546. }
  547. return result;
  548. }
  549. ///////////////////////////////////////////////////////////////////////////////////////////////////////
  550. LPCTSTR GetSocketErrorDesc(EnSocketError enCode)
  551. {
  552. switch(enCode)
  553. {
  554. case SE_OK: return _T("SUCCESS");
  555. case SE_ILLEGAL_STATE: return _T("Illegal State");
  556. case SE_INVALID_PARAM: return _T("Invalid Parameter");
  557. case SE_SOCKET_CREATE: return _T("Create SOCKET Fail");
  558. case SE_SOCKET_BIND: return _T("Bind SOCKET Fail");
  559. case SE_SOCKET_PREPARE: return _T("Prepare SOCKET Fail");
  560. case SE_SOCKET_LISTEN: return _T("Listen SOCKET Fail");
  561. case SE_CP_CREATE: return _T("Create IOCP Fail");
  562. case SE_WORKER_THREAD_CREATE: return _T("Create Worker Thread Fail");
  563. case SE_DETECT_THREAD_CREATE: return _T("Create Detector Thread Fail");
  564. case SE_SOCKE_ATTACH_TO_CP: return _T("Attach SOCKET to IOCP Fail");
  565. case SE_CONNECT_SERVER: return _T("Connect to Server Fail");
  566. case SE_NETWORK: return _T("Network Error");
  567. case SE_DATA_PROC: return _T("Process Data Error");
  568. case SE_DATA_SEND: return _T("Send Data Fail");
  569. case SE_SSL_ENV_NOT_READY: return _T("SSL environment not ready");
  570. default: ASSERT(FALSE); return _T("UNKNOWN ERROR");
  571. }
  572. }