开源的socket服务端客户端,支持C# C++

SocketHelper.cpp 19KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770
  1. /*
  2. * Copyright: JessMA Open Source (ldcsaa@gmail.com)
  3. *
  4. * Version : 4.1.3
  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. ULONGLONG NToH64(ULONGLONG value)
  199. {
  200. return (((ULONGLONG)ntohl((u_long)((value << 32) >> 32))) << 32) | ntohl((u_long)(value >> 32));
  201. }
  202. ULONGLONG HToN64(ULONGLONG value)
  203. {
  204. return (((ULONGLONG)htonl((u_long)((value << 32) >> 32))) << 32) | htonl((u_long)(value >> 32));
  205. }
  206. PVOID GetExtensionFuncPtr(SOCKET sock, GUID guid)
  207. {
  208. DWORD dwBytes;
  209. PVOID pfn = nullptr;
  210. ::WSAIoctl (
  211. sock,
  212. SIO_GET_EXTENSION_FUNCTION_POINTER,
  213. &guid,
  214. sizeof(guid),
  215. &pfn,
  216. sizeof(pfn),
  217. &dwBytes,
  218. nullptr,
  219. nullptr
  220. );
  221. return pfn;
  222. }
  223. LPFN_ACCEPTEX Get_AcceptEx_FuncPtr(SOCKET sock)
  224. {
  225. GUID guid = WSAID_ACCEPTEX;
  226. return (LPFN_ACCEPTEX)GetExtensionFuncPtr(sock, guid);
  227. }
  228. LPFN_GETACCEPTEXSOCKADDRS Get_GetAcceptExSockaddrs_FuncPtr(SOCKET sock)
  229. {
  230. GUID guid = WSAID_GETACCEPTEXSOCKADDRS;
  231. return (LPFN_GETACCEPTEXSOCKADDRS)GetExtensionFuncPtr(sock, guid);
  232. }
  233. LPFN_CONNECTEX Get_ConnectEx_FuncPtr(SOCKET sock)
  234. {
  235. GUID guid = WSAID_CONNECTEX;
  236. return (LPFN_CONNECTEX)GetExtensionFuncPtr(sock, guid);
  237. }
  238. LPFN_TRANSMITFILE Get_TransmitFile_FuncPtr(SOCKET sock)
  239. {
  240. GUID guid = WSAID_TRANSMITFILE;
  241. return (LPFN_TRANSMITFILE)GetExtensionFuncPtr(sock, guid);
  242. }
  243. LPFN_DISCONNECTEX Get_DisconnectEx_FuncPtr (SOCKET sock)
  244. {
  245. GUID guid = WSAID_DISCONNECTEX;
  246. return (LPFN_DISCONNECTEX)GetExtensionFuncPtr(sock, guid);
  247. }
  248. HRESULT ReadSmallFile(LPCTSTR lpszFileName, CAtlFile& file, CAtlFileMapping<>& fmap, DWORD dwMaxFileSize)
  249. {
  250. ASSERT(lpszFileName != nullptr);
  251. HRESULT hr = file.Create(lpszFileName, GENERIC_READ, FILE_SHARE_READ, OPEN_EXISTING);
  252. if(SUCCEEDED(hr))
  253. {
  254. ULONGLONG ullLen;
  255. hr = file.GetSize(ullLen);
  256. if(SUCCEEDED(hr))
  257. {
  258. if(ullLen > 0 && ullLen <= dwMaxFileSize)
  259. hr = fmap.MapFile(file);
  260. else if(ullLen == 0)
  261. hr = HRESULT_FROM_WIN32(ERROR_FILE_INVALID);
  262. else
  263. hr = HRESULT_FROM_WIN32(ERROR_FILE_TOO_LARGE);
  264. }
  265. }
  266. return hr;
  267. }
  268. HRESULT MakeSmallFilePackage(LPCTSTR lpszFileName, CAtlFile& file, CAtlFileMapping<>& fmap, WSABUF szBuf[3], const LPWSABUF pHead, const LPWSABUF pTail)
  269. {
  270. DWORD dwMaxFileSize = MAX_SMALL_FILE_SIZE - (pHead ? pHead->len : 0) - (pTail ? pTail->len : 0);
  271. ASSERT(dwMaxFileSize <= MAX_SMALL_FILE_SIZE);
  272. HRESULT hr = ReadSmallFile(lpszFileName, file, fmap, dwMaxFileSize);
  273. if(SUCCEEDED(hr))
  274. {
  275. szBuf[1].len = (ULONG)fmap.GetMappingSize();
  276. szBuf[1].buf = fmap;
  277. if(pHead) memcpy(&szBuf[0], pHead, sizeof(WSABUF));
  278. else memset(&szBuf[0], 0, sizeof(WSABUF));
  279. if(pTail) memcpy(&szBuf[2], pTail, sizeof(WSABUF));
  280. else memset(&szBuf[2], 0, sizeof(WSABUF));
  281. }
  282. return hr;
  283. }
  284. ///////////////////////////////////////////////////////////////////////////////////////////////////////
  285. BOOL PostIocpCommand(HANDLE hIOCP, EnIocpCommand enCmd, ULONG_PTR ulParam)
  286. {
  287. return ::PostQueuedCompletionStatus(hIOCP, enCmd, ulParam, nullptr);
  288. }
  289. BOOL PostIocpExit(HANDLE hIOCP)
  290. {
  291. return PostIocpCommand(hIOCP, IOCP_CMD_EXIT, 0);
  292. }
  293. BOOL PostIocpAccept(HANDLE hIOCP)
  294. {
  295. return PostIocpCommand(hIOCP, IOCP_CMD_ACCEPT, 0);
  296. }
  297. BOOL PostIocpDisconnect(HANDLE hIOCP, CONNID dwConnID)
  298. {
  299. return PostIocpCommand(hIOCP, IOCP_CMD_DISCONNECT, dwConnID);
  300. }
  301. BOOL PostIocpSend(HANDLE hIOCP, CONNID dwConnID)
  302. {
  303. return PostIocpCommand(hIOCP, IOCP_CMD_SEND, dwConnID);
  304. }
  305. BOOL PostIocpClose(HANDLE hIOCP, CONNID dwConnID, int iErrorCode)
  306. {
  307. return PostIocpCommand(hIOCP, (EnIocpCommand)iErrorCode, dwConnID);
  308. }
  309. ///////////////////////////////////////////////////////////////////////////////////////////////////////
  310. int SSO_SetSocketOption(SOCKET sock, int level, int name, LPVOID val, int len)
  311. {
  312. return setsockopt(sock, level, name, (CHAR*)val, len);
  313. }
  314. int SSO_GetSocketOption(SOCKET sock, int level, int name, LPVOID val, int* len)
  315. {
  316. return getsockopt(sock, level, name, (CHAR*)val, len);
  317. }
  318. int SSO_IoctlSocket(SOCKET sock, long cmd, u_long* arg)
  319. {
  320. return ioctlsocket(sock, cmd, arg);
  321. }
  322. int SSO_WSAIoctl(SOCKET sock, DWORD dwIoControlCode, LPVOID lpvInBuffer, DWORD cbInBuffer, LPVOID lpvOutBuffer, DWORD cbOutBuffer, LPDWORD lpcbBytesReturned)
  323. {
  324. return ::WSAIoctl(sock, dwIoControlCode, lpvInBuffer, cbInBuffer, lpvOutBuffer, cbOutBuffer, lpcbBytesReturned, nullptr, nullptr);
  325. }
  326. int SSO_UpdateAcceptContext(SOCKET soClient, SOCKET soBind)
  327. {
  328. return setsockopt(soClient, SOL_SOCKET, SO_UPDATE_ACCEPT_CONTEXT, (CHAR*)&soBind, sizeof(SOCKET));
  329. }
  330. int SSO_UpdateConnectContext(SOCKET soClient, int iOption)
  331. {
  332. return setsockopt(soClient, SOL_SOCKET, SO_UPDATE_CONNECT_CONTEXT, (CHAR*)&iOption, sizeof(int));
  333. }
  334. int SSO_NoDelay(SOCKET sock, BOOL bNoDelay)
  335. {
  336. return setsockopt(sock, IPPROTO_TCP, TCP_NODELAY, (CHAR*)&bNoDelay, sizeof(BOOL));
  337. }
  338. int SSO_DontLinger(SOCKET sock, BOOL bDont)
  339. {
  340. return setsockopt(sock, SOL_SOCKET, SO_DONTLINGER, (CHAR*)&bDont, sizeof(BOOL));
  341. }
  342. int SSO_Linger(SOCKET sock, USHORT l_onoff, USHORT l_linger)
  343. {
  344. linger ln = {l_onoff, l_linger};
  345. return setsockopt(sock, SOL_SOCKET, SO_LINGER, (CHAR*)&ln, sizeof(linger));
  346. }
  347. int SSO_KeepAlive(SOCKET sock, BOOL bKeepAlive)
  348. {
  349. return setsockopt(sock, SOL_SOCKET, SO_KEEPALIVE, (CHAR*)&bKeepAlive, sizeof(BOOL));
  350. }
  351. int SSO_KeepAliveVals(SOCKET sock, u_long onoff, u_long time, u_long interval)
  352. {
  353. int result = NO_ERROR;
  354. tcp_keepalive in = {onoff, time, interval};
  355. DWORD dwBytes;
  356. if(::WSAIoctl (
  357. sock,
  358. SIO_KEEPALIVE_VALS,
  359. (LPVOID)&in,
  360. sizeof(in),
  361. nullptr,
  362. 0,
  363. &dwBytes,
  364. nullptr,
  365. nullptr
  366. ) == SOCKET_ERROR)
  367. {
  368. result = ::WSAGetLastError();
  369. if(result == WSAEWOULDBLOCK)
  370. result = NO_ERROR;
  371. }
  372. return result;
  373. }
  374. int SSO_RecvBuffSize(SOCKET sock, int size)
  375. {
  376. return setsockopt(sock, SOL_SOCKET, SO_RCVBUF, (CHAR*)&size, sizeof(int));
  377. }
  378. int SSO_SendBuffSize(SOCKET sock, int size)
  379. {
  380. return setsockopt(sock, SOL_SOCKET, SO_SNDBUF, (CHAR*)&size, sizeof(int));
  381. }
  382. int SSO_ReuseAddress(SOCKET sock, BOOL bReuse)
  383. {
  384. return setsockopt(sock, SOL_SOCKET, SO_REUSEADDR, (CHAR*)&bReuse, sizeof(BOOL));
  385. }
  386. int SSO_UDP_ConnReset(SOCKET sock, BOOL bNewBehavior)
  387. {
  388. int result = NO_ERROR;
  389. DWORD dwBytes;
  390. if(::WSAIoctl (
  391. sock,
  392. SIO_UDP_CONNRESET,
  393. (LPVOID)&bNewBehavior,
  394. sizeof(bNewBehavior),
  395. nullptr,
  396. 0,
  397. &dwBytes,
  398. nullptr,
  399. nullptr
  400. ) == SOCKET_ERROR)
  401. {
  402. result = ::WSAGetLastError();
  403. if(result == WSAEWOULDBLOCK)
  404. result = NO_ERROR;
  405. }
  406. return result;
  407. }
  408. ///////////////////////////////////////////////////////////////////////////////////////////////////////
  409. CONNID GenerateConnectionID()
  410. {
  411. static volatile CONNID s_dwConnID = 0;
  412. CONNID dwConnID = ::InterlockedIncrement(&s_dwConnID);
  413. if(dwConnID == 0)
  414. dwConnID = ::InterlockedIncrement(&s_dwConnID);
  415. return dwConnID;
  416. }
  417. int ManualCloseSocket(SOCKET sock, int iShutdownFlag, BOOL bGraceful, BOOL bReuseAddress)
  418. {
  419. if(!bGraceful)
  420. SSO_Linger(sock, 1, 0);
  421. if(bReuseAddress)
  422. SSO_ReuseAddress(sock, bReuseAddress);
  423. if(iShutdownFlag != 0xFF)
  424. shutdown(sock, iShutdownFlag);
  425. return closesocket(sock);
  426. }
  427. int PostAccept(LPFN_ACCEPTEX pfnAcceptEx, SOCKET soListen, SOCKET soClient, TBufferObj* pBufferObj)
  428. {
  429. int result = PostAcceptNotCheck(pfnAcceptEx, soListen, soClient, pBufferObj);
  430. if(result == WSA_IO_PENDING)
  431. result = NO_ERROR;
  432. return result;
  433. }
  434. int PostAcceptNotCheck(LPFN_ACCEPTEX pfnAcceptEx, SOCKET soListen, SOCKET soClient, TBufferObj* pBufferObj)
  435. {
  436. int result = NO_ERROR;
  437. pBufferObj->client = soClient;
  438. pBufferObj->operation = SO_ACCEPT;
  439. if(!pfnAcceptEx (
  440. soListen,
  441. pBufferObj->client,
  442. pBufferObj->buff.buf,
  443. 0,
  444. sizeof(SOCKADDR_IN) + 16,
  445. sizeof(SOCKADDR_IN) + 16,
  446. nullptr,
  447. &pBufferObj->ov
  448. )
  449. )
  450. {
  451. result = ::WSAGetLastError();
  452. }
  453. return result;
  454. }
  455. int PostConnect(LPFN_CONNECTEX pfnConnectEx, SOCKET soClient, SOCKADDR_IN& soAddrIN, TBufferObj* pBufferObj)
  456. {
  457. int result = PostConnectNotCheck(pfnConnectEx, soClient, soAddrIN, pBufferObj);
  458. if(result == WSA_IO_PENDING)
  459. result = NO_ERROR;
  460. return result;
  461. }
  462. int PostConnectNotCheck(LPFN_CONNECTEX pfnConnectEx, SOCKET soClient, SOCKADDR_IN& soAddrIN, TBufferObj* pBufferObj)
  463. {
  464. int result = NO_ERROR;
  465. pBufferObj->client = soClient;
  466. pBufferObj->operation = SO_CONNECT;
  467. if(!pfnConnectEx (
  468. soClient,
  469. (SOCKADDR*)&soAddrIN,
  470. sizeof(SOCKADDR_IN),
  471. nullptr,
  472. 0,
  473. nullptr,
  474. &pBufferObj->ov
  475. )
  476. )
  477. {
  478. result = ::WSAGetLastError();
  479. }
  480. return result;
  481. }
  482. int PostSend(TSocketObj* pSocketObj, TBufferObj* pBufferObj)
  483. {
  484. int result = PostSendNotCheck(pSocketObj, pBufferObj);
  485. if(result == WSA_IO_PENDING)
  486. result = NO_ERROR;
  487. return result;
  488. }
  489. int PostSendNotCheck(TSocketObj* pSocketObj, TBufferObj* pBufferObj)
  490. {
  491. int result = NO_ERROR;
  492. DWORD dwBytes = 0;
  493. pBufferObj->client = pSocketObj->socket;
  494. pBufferObj->operation = SO_SEND;
  495. if(::WSASend(
  496. pBufferObj->client,
  497. &pBufferObj->buff,
  498. 1,
  499. &dwBytes,
  500. 0,
  501. &pBufferObj->ov,
  502. nullptr
  503. ) == SOCKET_ERROR)
  504. {
  505. result = ::WSAGetLastError();
  506. }
  507. return result;
  508. }
  509. int PostReceive(TSocketObj* pSocketObj, TBufferObj* pBufferObj)
  510. {
  511. int result = PostReceiveNotCheck(pSocketObj, pBufferObj);
  512. if(result == WSA_IO_PENDING)
  513. result = NO_ERROR;
  514. return result;
  515. }
  516. int PostReceiveNotCheck(TSocketObj* pSocketObj, TBufferObj* pBufferObj)
  517. {
  518. int result = NO_ERROR;
  519. DWORD dwFlag = 0;
  520. DWORD dwBytes = 0;
  521. pBufferObj->client = pSocketObj->socket;
  522. pBufferObj->operation = SO_RECEIVE;
  523. if(::WSARecv(
  524. pBufferObj->client,
  525. &pBufferObj->buff,
  526. 1,
  527. &dwBytes,
  528. &dwFlag,
  529. &pBufferObj->ov,
  530. nullptr
  531. ) == SOCKET_ERROR)
  532. {
  533. result = ::WSAGetLastError();
  534. }
  535. return result;
  536. }
  537. int PostSendTo(SOCKET sock, TUdpBufferObj* pBufferObj)
  538. {
  539. int result = PostSendToNotCheck(sock, pBufferObj);
  540. if(result == WSA_IO_PENDING)
  541. result = NO_ERROR;
  542. return result;
  543. }
  544. int PostSendToNotCheck(SOCKET sock, TUdpBufferObj* pBufferObj)
  545. {
  546. int result = NO_ERROR;
  547. DWORD dwBytes = 0;
  548. pBufferObj->operation = SO_SEND;
  549. pBufferObj->addrLen = sizeof(SOCKADDR_IN);
  550. if(::WSASendTo (
  551. sock,
  552. &pBufferObj->buff,
  553. 1,
  554. &dwBytes,
  555. 0,
  556. (sockaddr*)&pBufferObj->remoteAddr,
  557. pBufferObj->addrLen,
  558. &pBufferObj->ov,
  559. nullptr
  560. ) == SOCKET_ERROR)
  561. {
  562. result = ::WSAGetLastError();
  563. }
  564. return result;
  565. }
  566. int PostReceiveFrom(SOCKET sock, TUdpBufferObj* pBufferObj)
  567. {
  568. int result = PostReceiveFromNotCheck(sock, pBufferObj);
  569. if(result == WSA_IO_PENDING)
  570. result = NO_ERROR;
  571. return result;
  572. }
  573. int PostReceiveFromNotCheck(SOCKET sock, TUdpBufferObj* pBufferObj)
  574. {
  575. int result = NO_ERROR;
  576. DWORD dwFlag = 0;
  577. DWORD dwBytes = 0;
  578. pBufferObj->operation = SO_RECEIVE;
  579. pBufferObj->addrLen = sizeof(SOCKADDR_IN);
  580. ::ZeroMemory(&pBufferObj->remoteAddr, pBufferObj->addrLen);
  581. if(::WSARecvFrom(
  582. sock,
  583. &pBufferObj->buff,
  584. 1,
  585. &dwBytes,
  586. &dwFlag,
  587. (sockaddr*)&pBufferObj->remoteAddr,
  588. &pBufferObj->addrLen,
  589. &pBufferObj->ov,
  590. nullptr
  591. ) == SOCKET_ERROR)
  592. {
  593. result = ::WSAGetLastError();
  594. }
  595. return result;
  596. }
  597. ///////////////////////////////////////////////////////////////////////////////////////////////////////
  598. LPCTSTR GetSocketErrorDesc(EnSocketError enCode)
  599. {
  600. switch(enCode)
  601. {
  602. case SE_OK: return _T("SUCCESS");
  603. case SE_ILLEGAL_STATE: return _T("Illegal State");
  604. case SE_INVALID_PARAM: return _T("Invalid Parameter");
  605. case SE_SOCKET_CREATE: return _T("Create SOCKET Fail");
  606. case SE_SOCKET_BIND: return _T("Bind SOCKET Fail");
  607. case SE_SOCKET_PREPARE: return _T("Prepare SOCKET Fail");
  608. case SE_SOCKET_LISTEN: return _T("Listen SOCKET Fail");
  609. case SE_CP_CREATE: return _T("Create IOCP Fail");
  610. case SE_WORKER_THREAD_CREATE: return _T("Create Worker Thread Fail");
  611. case SE_DETECT_THREAD_CREATE: return _T("Create Detector Thread Fail");
  612. case SE_SOCKE_ATTACH_TO_CP: return _T("Attach SOCKET to IOCP Fail");
  613. case SE_CONNECT_SERVER: return _T("Connect to Server Fail");
  614. case SE_NETWORK: return _T("Network Error");
  615. case SE_DATA_PROC: return _T("Process Data Error");
  616. case SE_DATA_SEND: return _T("Send Data Fail");
  617. case SE_SSL_ENV_NOT_READY: return _T("SSL environment not ready");
  618. default: ASSERT(FALSE); return _T("UNKNOWN ERROR");
  619. }
  620. }
  621. DWORD GetHPSocketVersion()
  622. {
  623. static DWORD s_dwVersion = (HP_VERSION_MAJOR << 24) | (HP_VERSION_MINOR << 16) | (HP_VERSION_REVISE << 8) | HP_VERSION_BUILD;
  624. return s_dwVersion;
  625. }