IOCPSocketServer.cpp 16 KB

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