IOCPSocketServer.cpp 16 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754
  1. #include "IOCPSocketServer.h"
  2. #include <list>
  3. #if defined(_MSC_VER)
  4. #include <process.h>
  5. #endif
  6. #include "dbgutil.h"
  7. #if defined(_MSC_VER)
  8. enum OperationType
  9. {
  10. OT_ACCEPT,
  11. OT_SEND,
  12. OT_RECEIVE,
  13. };
  14. struct CIOCPSocketServer::OperationContext : OVERLAPPED
  15. {
  16. int nConnectionID;
  17. SOCKET hSocket;
  18. OperationType eOperationType;
  19. WSABUF WsaBuf;
  20. char *pBuf;
  21. int nTotalBytes;
  22. int nLeftBytes;
  23. OperationContext(OperationType t, int id, SOCKET s):
  24. nConnectionID(id),
  25. hSocket(s),
  26. eOperationType(t),
  27. pBuf(NULL),
  28. nTotalBytes(0),
  29. nLeftBytes(0)
  30. {
  31. }
  32. ~OperationContext()
  33. {
  34. if (pBuf != NULL)
  35. {
  36. delete pBuf;
  37. pBuf = NULL;
  38. }
  39. }
  40. void PrepareBuffer(int nBufLen = 8192)
  41. {
  42. memset(this, 0, sizeof(OVERLAPPED));
  43. pBuf =new char[nBufLen];
  44. memset(pBuf, 0, nBufLen);
  45. nTotalBytes = nBufLen;
  46. nLeftBytes = nBufLen;
  47. WsaBuf.buf = pBuf;
  48. WsaBuf.len = nBufLen;
  49. }
  50. bool AddSendLen(int nTransferLen)
  51. {
  52. memset(this, 0, sizeof(OVERLAPPED));
  53. if (nLeftBytes >0)
  54. {
  55. nLeftBytes -= nTransferLen;
  56. WsaBuf.buf = pBuf + nTotalBytes - nLeftBytes;
  57. WsaBuf.len = nLeftBytes;
  58. }
  59. return nLeftBytes > 0;
  60. }
  61. void SetSendData(char *pData, int nLen)
  62. {
  63. memset(this, 0, sizeof(OVERLAPPED));
  64. if (NULL != pBuf)
  65. {
  66. delete[] pBuf;
  67. pBuf = NULL;
  68. }
  69. pBuf = new char[nLen];
  70. memcpy(pBuf, pData, nLen);
  71. nTotalBytes = nLeftBytes = nLen;
  72. WsaBuf.buf = pBuf;
  73. WsaBuf.len = nLen;
  74. }
  75. };
  76. struct CIOCPSocketServer::ConnectionContext
  77. {
  78. int nConnectionID;
  79. SOCKET hSocket;
  80. ConnectionContext(int nConnectionID, SOCKET hSocket):
  81. nConnectionID(nConnectionID),
  82. hSocket(hSocket)
  83. {
  84. }
  85. ~ConnectionContext()
  86. {
  87. if (hSocket != INVALID_SOCKET)
  88. {
  89. closesocket(hSocket);
  90. hSocket = INVALID_SOCKET;
  91. }
  92. }
  93. };
  94. #endif
  95. CIOCPSocketServer::CIOCPSocketServer(int nMaxWorkThreadNum)
  96. #if defined(_MSC_VER)
  97. :m_dwSerialNo(0),
  98. m_hIOCP(INVALID_HANDLE_VALUE),
  99. m_hListenSocket(INVALID_SOCKET),
  100. m_pAcceptContext(NULL),
  101. m_nThreadCount(0),
  102. m_pWorkThreads(NULL),
  103. m_bExit(false),
  104. m_bStarted(false),
  105. m_fnAcceptEx(NULL),
  106. m_fnGetAcceptExSocketAddrs(NULL),
  107. m_nMaxWorkThreadNum(nMaxWorkThreadNum)
  108. #endif
  109. {
  110. }
  111. CIOCPSocketServer::~CIOCPSocketServer(void)
  112. {
  113. #if defined(_MSC_VER)
  114. CAutoLock lock(&m_LockObject);
  115. for(auto it = m_ConnectionContext.begin(); it!=m_ConnectionContext.end(); it++)
  116. {
  117. delete (*it).second;
  118. }
  119. if (m_pWorkThreads != NULL && m_nThreadCount >0)
  120. {
  121. for(int i=0; i<m_nThreadCount; i++)
  122. CloseHandle(m_pWorkThreads[i]);
  123. delete m_pWorkThreads;
  124. m_pWorkThreads = NULL;
  125. m_nThreadCount = 0;
  126. }
  127. if (m_hIOCP != INVALID_HANDLE_VALUE)
  128. {
  129. CloseHandle(m_hIOCP);
  130. m_hIOCP = INVALID_HANDLE_VALUE;
  131. }
  132. if (m_hListenSocket != INVALID_SOCKET)
  133. {
  134. closesocket(m_hListenSocket);
  135. m_hListenSocket = INVALID_SOCKET;
  136. }
  137. if (m_pAcceptContext != NULL)
  138. {
  139. delete m_pAcceptContext;
  140. m_pAcceptContext = NULL;
  141. }
  142. #endif
  143. }
  144. #if defined(_MSC_VER)
  145. bool CIOCPSocketServer::WinSockStartup()
  146. {
  147. WSADATA wsaData = {};
  148. return WSAStartup(0x202, &wsaData) == 0;
  149. }
  150. bool CIOCPSocketServer::WinSockCleanup()
  151. {
  152. return WSACleanup() == 0;
  153. }
  154. const char* CIOCPSocketServer::GetLastErrorMsg(int nErrorCode)
  155. {
  156. if (nErrorCode == 0)
  157. nErrorCode = GetLastError();
  158. char pMsg[1024];
  159. memset(pMsg, 0, sizeof(pMsg));
  160. if(::FormatMessage(
  161. FORMAT_MESSAGE_IGNORE_INSERTS | FORMAT_MESSAGE_FROM_SYSTEM,
  162. NULL,
  163. nErrorCode,
  164. MAKELANGID(LANG_NEUTRAL,SUBLANG_DEFAULT),
  165. pMsg,
  166. sizeof(pMsg)/sizeof(char),
  167. NULL))
  168. {
  169. pMsg[sizeof(pMsg)/sizeof(char)-1]=0;
  170. }
  171. m_strLastErrMsg = pMsg;
  172. return m_strLastErrMsg.c_str();
  173. }
  174. int CIOCPSocketServer::GetProcessorNum()
  175. {
  176. static int nProcessors = 0;
  177. if (0 == nProcessors)
  178. {
  179. SYSTEM_INFO si;
  180. GetSystemInfo(&si);
  181. nProcessors = si.dwNumberOfProcessors;
  182. }
  183. return nProcessors;
  184. }
  185. bool CIOCPSocketServer::StartListen(int nListenPort)
  186. {
  187. if (m_bStarted)
  188. return true;
  189. m_bExit = false;
  190. m_hIOCP = CreateIoCompletionPort(INVALID_HANDLE_VALUE, NULL, 0, 0);
  191. if (m_hIOCP == NULL)
  192. return false;
  193. UINT nThreadID(0);
  194. //Overlapped I/O follows the model established in Windows and can be performed only on
  195. //sockets created through the WSASocket function
  196. m_hListenSocket = WSASocket(AF_INET, SOCK_STREAM, 0, NULL, 0, WSA_FLAG_OVERLAPPED);
  197. if (m_hListenSocket == INVALID_SOCKET)
  198. goto error;
  199. sockaddr_in addr;
  200. ZeroMemory((char *)&addr, sizeof(addr));
  201. addr.sin_family = AF_INET;
  202. addr.sin_addr.s_addr = htonl(INADDR_ANY);
  203. addr.sin_port = htons(nListenPort);
  204. if (SOCKET_ERROR == bind(m_hListenSocket, (struct sockaddr *) &addr, sizeof(addr)))
  205. goto error;
  206. // bind to iocp
  207. if (CreateIoCompletionPort((HANDLE)m_hListenSocket, m_hIOCP, 0, 0) == NULL)
  208. goto error;
  209. if (SOCKET_ERROR == listen(m_hListenSocket,SOMAXCONN))
  210. goto error;
  211. // begin accept
  212. if (!AsyncAccept())
  213. goto error;
  214. // create work thread
  215. m_nThreadCount = m_nMaxWorkThreadNum >0 ? m_nMaxWorkThreadNum : 2 * GetProcessorNum();
  216. m_pWorkThreads = new HANDLE[m_nThreadCount];
  217. int i;
  218. for(i=0; i<m_nThreadCount; i++)
  219. {
  220. m_pWorkThreads[i] = (HANDLE)_beginthreadex(NULL, 0, &WorkThreadFunc, this, 0, &nThreadID);
  221. }
  222. m_bStarted = true;
  223. return true;
  224. error:
  225. if (m_hIOCP != INVALID_HANDLE_VALUE)
  226. {
  227. CloseHandle(m_hIOCP);
  228. m_hIOCP = INVALID_HANDLE_VALUE;
  229. }
  230. if (m_hListenSocket != INVALID_SOCKET)
  231. {
  232. closesocket(m_hListenSocket);
  233. m_hListenSocket = INVALID_SOCKET;
  234. }
  235. return false;
  236. }
  237. UINT CIOCPSocketServer::WorkThreadFunc(void *pArg)
  238. {
  239. CIOCPSocketServer *pThis = (CIOCPSocketServer*) pArg;
  240. while(pThis->PollCompletionPort());
  241. // 退出线程
  242. _endthreadex(0);
  243. return 0;
  244. }
  245. bool CIOCPSocketServer::PollCompletionPort()
  246. {
  247. OperationContext *pOperationContext = NULL;
  248. DWORD dwTemp = 0;
  249. DWORD dwBytesTransfered = 0;
  250. BOOL bRet = GetQueuedCompletionStatus(
  251. m_hIOCP,
  252. &dwBytesTransfered,
  253. (LPDWORD)&dwTemp,
  254. (LPOVERLAPPED *)&pOperationContext,
  255. INFINITE);
  256. // should exit now
  257. if (pOperationContext == NULL)
  258. return false;
  259. if ((!bRet || (bRet && 0 == dwBytesTransfered)) && pOperationContext->eOperationType != OT_ACCEPT)
  260. {
  261. int nConnectionID = pOperationContext->nConnectionID;
  262. CloseConnection(nConnectionID);
  263. OnClose(nConnectionID);
  264. delete pOperationContext;
  265. return true;
  266. }
  267. switch (pOperationContext->eOperationType)
  268. {
  269. case OT_ACCEPT:
  270. ProcessAcceptCompleted(pOperationContext);
  271. break;
  272. case OT_SEND:
  273. ProcessSendCompleted(pOperationContext, dwBytesTransfered);
  274. break;
  275. case OT_RECEIVE:
  276. ProcessReceiveCompleted(pOperationContext, dwBytesTransfered);
  277. break;
  278. }
  279. return true;
  280. }
  281. bool CIOCPSocketServer::StopListen()
  282. {
  283. if (!m_bStarted)
  284. return false;
  285. m_bExit = true;
  286. m_bStarted = false;
  287. for (int i = 0; i < m_nThreadCount; i++)
  288. {
  289. //Help threads get out of blocking - GetQueuedCompletionStatus()
  290. PostQueuedCompletionStatus(m_hIOCP, 0, (DWORD) NULL, NULL);
  291. }
  292. WaitForMultipleObjects(m_nThreadCount, m_pWorkThreads, TRUE, INFINITE);
  293. for (int i = 0; i < m_nThreadCount; i++)
  294. {
  295. CloseHandle(m_pWorkThreads[i]);
  296. }
  297. delete[] m_pWorkThreads;
  298. m_pWorkThreads = NULL;
  299. if (m_pAcceptContext != NULL)
  300. {
  301. if (m_pAcceptContext->hSocket != INVALID_SOCKET)
  302. closesocket(m_pAcceptContext->hSocket);
  303. delete m_pAcceptContext;
  304. m_pAcceptContext = NULL;
  305. }
  306. SetNoLinger(m_hListenSocket);
  307. closesocket(m_hListenSocket);
  308. m_hListenSocket = INVALID_SOCKET;
  309. for(auto it = m_ConnectionContext.begin(); it != m_ConnectionContext.end(); it++)
  310. {
  311. delete (*it).second;
  312. }
  313. m_ConnectionContext.clear();
  314. CloseHandle(m_hIOCP);
  315. m_hIOCP = NULL;
  316. return true;
  317. }
  318. bool CIOCPSocketServer::AsyncAccept()
  319. {
  320. if (m_fnAcceptEx == NULL)
  321. {
  322. // Load the AcceptEx extension function from the provider for this socket
  323. GUID acceptex_guid = WSAID_ACCEPTEX;
  324. if (!LoadExtensionFunction(m_hListenSocket, acceptex_guid, (void**)&m_fnAcceptEx))
  325. {
  326. GetLastErrorMsg(WSAGetLastError());
  327. return false;
  328. }
  329. }
  330. if (m_pAcceptContext == NULL)
  331. {
  332. int nReceiveBufLen = 8192;
  333. m_pAcceptContext = new OperationContext(OT_ACCEPT, 0, INVALID_SOCKET);
  334. m_pAcceptContext->pBuf =new char[nReceiveBufLen];
  335. memset(m_pAcceptContext->pBuf, 0, nReceiveBufLen);
  336. m_pAcceptContext->nTotalBytes = m_pAcceptContext->nLeftBytes = nReceiveBufLen;
  337. m_pAcceptContext->WsaBuf.buf = m_pAcceptContext->pBuf;
  338. m_pAcceptContext->WsaBuf.len = nReceiveBufLen;
  339. }
  340. TOOLKIT_ASSERT(m_pAcceptContext->hSocket == INVALID_SOCKET);
  341. m_pAcceptContext->hSocket = WSASocket(AF_INET, SOCK_STREAM, 0, NULL, 0, WSA_FLAG_OVERLAPPED);
  342. memset(m_pAcceptContext, 0, sizeof(OVERLAPPED));
  343. DWORD dwRecvNumBytes(0);
  344. BOOL bRet = m_fnAcceptEx(m_hListenSocket,
  345. m_pAcceptContext->hSocket,
  346. (LPVOID)(m_pAcceptContext->pBuf),
  347. 0,
  348. GetAddressSize() + 16,
  349. GetAddressSize() + 16,
  350. &dwRecvNumBytes,
  351. m_pAcceptContext);
  352. if (bRet)
  353. {
  354. // Accept completed synchronously. We need to marshal the data recieved over to the
  355. // worker thread ourselves...
  356. //PostQueuedCompletionStatus(m_hIOCP, dwRecvNumBytes, 0, m_pAcceptContext);
  357. }
  358. else
  359. if (!bRet && ERROR_IO_PENDING != WSAGetLastError())
  360. {
  361. GetLastErrorMsg();
  362. closesocket(m_pAcceptContext->hSocket);
  363. m_pAcceptContext->hSocket = INVALID_SOCKET;
  364. return false;
  365. }
  366. return true;
  367. }
  368. bool CIOCPSocketServer::AsyncSend(int nConnectionID, char *pData, int nSendLen)
  369. {
  370. if (!m_bStarted)
  371. {
  372. m_strLastErrMsg = "service not started";
  373. return false;
  374. }
  375. if (m_bExit)
  376. {
  377. m_strLastErrMsg = "service has stopped";
  378. return false;
  379. }
  380. auto pConnectionContext = GetConnectionContext(nConnectionID);
  381. if (pConnectionContext == NULL)
  382. {
  383. m_strLastErrMsg = "connection not exist";
  384. return false;
  385. }
  386. auto pSendContext = new OperationContext(OT_SEND, nConnectionID, pConnectionContext->hSocket);
  387. pSendContext->SetSendData(pData, nSendLen);
  388. DWORD dwBytesSend(0);
  389. int nRet = WSASend(pSendContext->hSocket, &pSendContext->WsaBuf, 1, &dwBytesSend, 0, pSendContext, NULL);
  390. if( nRet == SOCKET_ERROR && (ERROR_IO_PENDING != WSAGetLastError()) )
  391. {
  392. delete pSendContext;
  393. GetLastErrorMsg();
  394. CloseConnection(nConnectionID);
  395. return false;
  396. }
  397. return true;
  398. }
  399. CIOCPSocketServer::ConnectionContext* CIOCPSocketServer::GetConnectionContext(int nConnectionID)
  400. {
  401. CAutoLock lock(&m_LockObject);
  402. auto it = m_ConnectionContext.find(nConnectionID);
  403. if (it == m_ConnectionContext.end())
  404. return NULL;
  405. return (*it).second;
  406. }
  407. bool CIOCPSocketServer::CloseConnection(int nConnectionID)
  408. {
  409. CAutoLock lock(&m_LockObject);
  410. auto it = m_ConnectionContext.find(nConnectionID);
  411. if (it == m_ConnectionContext.end())
  412. return false;
  413. auto pSocketConnection = (*it).second;
  414. m_ConnectionContext.erase(nConnectionID);
  415. delete pSocketConnection;
  416. return true;
  417. }
  418. void CIOCPSocketServer::ProcessAcceptCompleted(OperationContext *pOperationContext)
  419. {
  420. TOOLKIT_ASSERT(NULL != pOperationContext);
  421. SOCKET hAcceptedSocket = pOperationContext->hSocket;
  422. if (!IsConnected(hAcceptedSocket))
  423. goto error;
  424. // When the AcceptEx function returns, the socket sAcceptSocket is
  425. // in the default state for a connected socket. The socket sAcceptSocket
  426. // does not inherit the properties of the socket associated with
  427. // sListenSocket parameter until SO_UPDATE_ACCEPT_CONTEXT is set on
  428. // the socket. Use the setsockopt function to set the SO_UPDATE_ACCEPT_CONTEXT
  429. // option, specifying sAcceptSocket as the socket handle and sListenSocket
  430. // as the option value.
  431. int nRet = setsockopt(
  432. hAcceptedSocket,
  433. SOL_SOCKET,
  434. SO_UPDATE_ACCEPT_CONTEXT,
  435. (char *)&m_hListenSocket,
  436. sizeof(m_hListenSocket)
  437. );
  438. if( nRet == SOCKET_ERROR )
  439. goto error;
  440. if (m_fnGetAcceptExSocketAddrs == NULL)
  441. {
  442. GUID guidGetAcceptExSockaddrs = WSAID_GETACCEPTEXSOCKADDRS;
  443. if (!LoadExtensionFunction(m_hListenSocket, guidGetAcceptExSockaddrs, (void**)&m_fnGetAcceptExSocketAddrs))
  444. goto error;
  445. }
  446. INT sizeOfLocalAddress = 0;
  447. INT sizeOfRemoteAddress = 0;
  448. sockaddr_in *pLocalAddress = 0;
  449. sockaddr_in *pRemoteAddress = 0;
  450. const size_t sizeOfAddress = GetAddressSize() + 16;
  451. m_fnGetAcceptExSocketAddrs(pOperationContext->pBuf, 0,
  452. sizeOfAddress,
  453. sizeOfAddress,
  454. (sockaddr**)&pLocalAddress,
  455. &sizeOfLocalAddress,
  456. (sockaddr**)&pRemoteAddress,
  457. &sizeOfRemoteAddress);
  458. // bind to iocp
  459. if (CreateIoCompletionPort((HANDLE)hAcceptedSocket, m_hIOCP, 0, 0) == NULL)
  460. goto error;
  461. // add into connection context map
  462. int nConnectionID = InterlockedIncrement(&m_dwSerialNo);
  463. ConnectionContext *pConnectionContext = new ConnectionContext(nConnectionID, hAcceptedSocket);
  464. {
  465. CAutoLock lock(&m_LockObject);
  466. m_ConnectionContext[nConnectionID] = pConnectionContext;
  467. pOperationContext->hSocket = INVALID_SOCKET;
  468. }
  469. // issue next accept
  470. AsyncAccept();
  471. // issue first receive
  472. auto pRecvContext = new OperationContext(OT_RECEIVE, nConnectionID, hAcceptedSocket);
  473. pRecvContext->PrepareBuffer();
  474. DWORD dwFlags(0), dwBytesRecvd(0);
  475. nRet = WSARecv(hAcceptedSocket, &pRecvContext->WsaBuf, 1, &dwBytesRecvd, &dwFlags, pRecvContext, NULL);
  476. //if (0 == nRet)
  477. //{
  478. // complete immediately
  479. //PostQueuedCompletionStatus(m_hIOCP, dwBytesRecvd, 0, pRecvContext);
  480. //}
  481. //else
  482. if (SOCKET_ERROR == nRet && WSAGetLastError() != ERROR_IO_PENDING)
  483. {
  484. delete pRecvContext;
  485. GetLastErrorMsg();
  486. CloseConnection(nConnectionID);
  487. goto error;
  488. }
  489. // OnAccepte
  490. OnAccepte(nConnectionID, inet_ntoa(pRemoteAddress->sin_addr), ntohs(pRemoteAddress->sin_port));
  491. return;
  492. error:
  493. GetLastErrorMsg();
  494. {
  495. CAutoLock lock(&m_LockObject);
  496. closesocket(pOperationContext->hSocket);
  497. pOperationContext->hSocket = INVALID_SOCKET;
  498. }
  499. }
  500. void CIOCPSocketServer::ProcessSendCompleted(OperationContext *pOperationContext, int nByteLen)
  501. {
  502. TOOLKIT_ASSERT(nByteLen >0 && pOperationContext!=NULL);
  503. int nConnectionID = pOperationContext->nConnectionID;
  504. // OnSend event
  505. OnSend(nConnectionID, nByteLen);
  506. if (!pOperationContext->AddSendLen(nByteLen) || !IsConnected(pOperationContext->hSocket))
  507. {
  508. delete pOperationContext;
  509. return;
  510. }
  511. DWORD dwBytesSend(0);
  512. int nRet = WSASend(pOperationContext->hSocket,
  513. &pOperationContext->WsaBuf, 1,
  514. &dwBytesSend, 0,
  515. pOperationContext, NULL);
  516. //if (0 == nRet)
  517. //{
  518. // // complete immediately
  519. // PostQueuedCompletionStatus(m_hIOCP, dwBytesSend, 0, pNextSendContext);
  520. //}
  521. //else
  522. if (SOCKET_ERROR == nRet && WSAGetLastError() != ERROR_IO_PENDING)
  523. {
  524. delete pOperationContext;
  525. GetLastErrorMsg();
  526. CloseConnection(nConnectionID);
  527. }
  528. }
  529. void CIOCPSocketServer::ProcessReceiveCompleted(OperationContext *pOperationContext, int nByteLen)
  530. {
  531. TOOLKIT_ASSERT(nByteLen >0);
  532. int nConnectionID = pOperationContext->nConnectionID;
  533. OnReceive(nConnectionID, pOperationContext->pBuf, nByteLen);
  534. if (! IsConnected(pOperationContext->hSocket))
  535. {
  536. delete pOperationContext;
  537. return;
  538. }
  539. DWORD dwFlags(0), dwBytesRecvd(0);
  540. memset(pOperationContext, 0, sizeof(OVERLAPPED));
  541. int nRet = WSARecv(pOperationContext->hSocket, &pOperationContext->WsaBuf, 1, &dwBytesRecvd, &dwFlags, pOperationContext, NULL);
  542. //if (0 == nRet)
  543. //{
  544. // // complete immediately
  545. // PostQueuedCompletionStatus(m_hIOCP, dwBytesRecvd, 0, pNextRecvContext);
  546. //}
  547. //else
  548. if (SOCKET_ERROR == nRet && WSAGetLastError() != ERROR_IO_PENDING)
  549. {
  550. delete pOperationContext;
  551. GetLastErrorMsg();
  552. CloseConnection(nConnectionID);
  553. }
  554. }
  555. DWORD CIOCPSocketServer::GetConnectTime(SOCKET hSocket)
  556. {
  557. if (INVALID_SOCKET != hSocket)
  558. {
  559. INT seconds;
  560. INT bytes = sizeof(seconds);
  561. if (NO_ERROR == ::getsockopt(
  562. hSocket,
  563. SOL_SOCKET, SO_CONNECT_TIME,
  564. (char *)&seconds,
  565. (PINT)&bytes))
  566. {
  567. return seconds;
  568. }
  569. else
  570. {
  571. GetLastErrorMsg(WSAGetLastError());
  572. }
  573. }
  574. //lint -e{569} Loss of information (return) (32 bits to 31 bits)
  575. return 0xFFFFFFFF;
  576. }
  577. bool CIOCPSocketServer::IsConnected(SOCKET hSocket)
  578. {
  579. return GetConnectTime(hSocket) != 0xFFFFFFFF;
  580. }
  581. size_t CIOCPSocketServer::GetAddressSize() const
  582. {
  583. return sizeof(SOCKADDR_IN);
  584. }
  585. bool CIOCPSocketServer::SetNoLinger(SOCKET hSocket)
  586. {
  587. // Force an abortive close.
  588. LINGER lingerStruct;
  589. lingerStruct.l_onoff = 1;
  590. lingerStruct.l_linger = 0;
  591. return SOCKET_ERROR != ::setsockopt(hSocket, SOL_SOCKET, SO_LINGER, (char *)&lingerStruct, sizeof(lingerStruct));
  592. }
  593. bool CIOCPSocketServer::LoadExtensionFunction(SOCKET s, GUID functionID, void **ppFunc)
  594. {
  595. DWORD dwBytes = 0;
  596. bool ok = true;
  597. if (0 != WSAIoctl(
  598. s,
  599. SIO_GET_EXTENSION_FUNCTION_POINTER,
  600. &functionID,
  601. sizeof(GUID),
  602. ppFunc,
  603. sizeof(void *),
  604. &dwBytes,
  605. 0,
  606. 0))
  607. {
  608. ok = false;
  609. }
  610. return ok;
  611. }
  612. #endif /*RVC_OS_WIN*/