AsyncSocketServerImpl.h 20 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633
  1. #ifndef ASYNCSOCKETSERVERIMPL_H
  2. #define ASYNCSOCKETSERVERIMPL_H
  3. #pragma once
  4. #pragma warning(push)
  5. #pragma warning(disable:4995)
  6. #include <vector>
  7. #include <list>
  8. #include <algorithm>
  9. #pragma warning(pop)
  10. #include "CritSection.h"
  11. #include "SocketHandle.h"
  12. /**
  13. * SocketIOBuffer
  14. * Overlapped I/O buffer
  15. */
  16. class SocketIOBuffer // Jeff,作者肯定没看过Windows核心编程第10章关于I/O完成端口的巧用;
  17. {
  18. WSAOVERLAPPED _Overlapped;
  19. SOCKET _socket;
  20. SockAddrIn _sockAddr;
  21. std::vector<unsigned char> _data;
  22. SocketIOBuffer();
  23. public:
  24. unsigned char szpendingbuf[SOCKET_BUFFSIZE];
  25. unsigned int npendingSize;
  26. public:
  27. SocketIOBuffer(SOCKET sock):_socket(sock)
  28. {
  29. // by default - no allocation
  30. npendingSize = 0;
  31. memset(szpendingbuf,0,SOCKET_BUFFSIZE);
  32. memset(&_Overlapped, 0, sizeof(_Overlapped));
  33. }
  34. explicit SocketIOBuffer(SOCKET sock, size_t size): _socket(sock)
  35. {
  36. npendingSize = 0;
  37. memset(szpendingbuf,0,SOCKET_BUFFSIZE);
  38. memset(&_Overlapped, 0, sizeof(_Overlapped));
  39. _data.resize( size );
  40. }
  41. SocketIOBuffer(const SocketIOBuffer& sbuf)
  42. {
  43. Copy(sbuf);
  44. }
  45. SocketIOBuffer& operator=(const SocketIOBuffer& sbuf)
  46. {
  47. return Copy(sbuf);
  48. }
  49. ~SocketIOBuffer()
  50. {
  51. Free();
  52. }
  53. bool IsValid() const { return (_socket != INVALID_SOCKET); }
  54. void ReAlloc( size_t count) { _data.resize(count); }
  55. void Free() { _data.clear(); }
  56. size_t BufferSize() const { return _data.size(); }
  57. SocketIOBuffer& Copy(const SocketIOBuffer& sbuf)
  58. {
  59. if ( this != &sbuf )
  60. {
  61. _socket = sbuf._socket;
  62. _sockAddr = sbuf._sockAddr;
  63. if ( !sbuf._data.empty() )
  64. {
  65. _data.resize( sbuf._data.size() );
  66. memcpy(&_data[0], &(sbuf._data[0]), _data.size());
  67. }
  68. // Jeff.add----.
  69. npendingSize = sbuf.npendingSize;
  70. memset(szpendingbuf,0,SOCKET_BUFFSIZE);
  71. memcpy(szpendingbuf,sbuf.szpendingbuf,npendingSize);
  72. // Jeff.add----.
  73. }
  74. return *this;
  75. }
  76. // Quick access operator
  77. operator SOCKET() { return _socket; }
  78. operator SOCKET() const { return _socket; }
  79. operator SockAddrIn&() { return _sockAddr; }
  80. operator const SockAddrIn&() const { return _sockAddr; }
  81. operator LPSOCKADDR() { return _sockAddr; }
  82. operator LPWSAOVERLAPPED() { return &_Overlapped; }
  83. operator LPBYTE() { return &_data[0]; }
  84. bool IsEqual(const SocketIOBuffer& sbuf) const { return (_socket == sbuf._socket); }
  85. bool operator==(const SocketIOBuffer& sbuf) const { return IsEqual( sbuf ); }
  86. bool operator==(SOCKET sock) const { return (_socket == sock); }
  87. bool operator!=(const SocketIOBuffer& sbuf) const { return !IsEqual( sbuf ); }
  88. };
  89. typedef std::list<SocketIOBuffer> SocketBufferList;
  90. static DWORD WM_ADD_CONNECTION = WM_USER+0x101;
  91. /**
  92. * IASocketServerHandler
  93. * Event handler that ASocketServerImpl<T> must implement
  94. * This class is not required, you can do the same thing as long your class exposes these functions.
  95. * (These functions are not pure to save you some typing)
  96. */
  97. class IASocketServerHandler
  98. {
  99. public:
  100. virtual void OnThreadBegin(CSocketHandle* ) {}
  101. virtual void OnThreadExit(CSocketHandle* ) {}
  102. virtual void OnThreadLoopEnter(CSocketHandle* ) {}
  103. virtual void OnThreadLoopLeave(CSocketHandle* ) {}
  104. virtual void OnAddConnection(CSocketHandle* , SOCKET ) {}
  105. virtual void OnRemoveConnection(CSocketHandle* , SOCKET ) {}
  106. // virtual void OnDataReceived(CSocketHandle* , const BYTE* , DWORD , const SockAddrIn& ) {}
  107. virtual void OnDataReceived(LPWSAOVERLAPPED , const BYTE* , DWORD , const SockAddrIn& ) {}
  108. virtual void OnConnectionFailure(CSocketHandle*, SOCKET) {}
  109. virtual void OnConnectionDropped(CSocketHandle* ) {}
  110. virtual void OnConnectionError(CSocketHandle* , DWORD ) {}
  111. };
  112. /**
  113. * ASocketServerImpl<T, tBufferSize>
  114. * Because <typename T> may refer to any class of your choosing,
  115. * Server Communication wrapper
  116. */
  117. template <typename T, size_t tBufferSize = 2048>
  118. class ASocketServerImpl
  119. {
  120. typedef ASocketServerImpl<T, tBufferSize> thisClass;
  121. public:
  122. ASocketServerImpl()
  123. : _pInterface(0)
  124. , _thread(0)
  125. , _threadId(0)
  126. {
  127. }
  128. void SetInterface(T* pInterface)
  129. {
  130. ::InterlockedExchangePointer(reinterpret_cast<void**>(&_pInterface), pInterface);
  131. }
  132. operator CSocketHandle*() throw()
  133. {
  134. return( &_socket );
  135. }
  136. CSocketHandle* operator->() throw()
  137. {
  138. return( &_socket );
  139. }
  140. bool IsOpen() const
  141. {
  142. return _socket.IsOpen();
  143. }
  144. bool CreateSocket(LPCTSTR pszHost, LPCTSTR pszServiceName, int nFamily, int nType, UINT uOptions = 0)
  145. {
  146. return _socket.CreateSocket(pszHost, pszServiceName, nFamily, nType, uOptions);
  147. }
  148. void Close()
  149. {
  150. _socket.Close();
  151. }
  152. DWORD Read(LPBYTE lpBuffer, DWORD dwSize, LPSOCKADDR lpAddrIn = NULL, DWORD dwTimeout = INFINITE)
  153. {
  154. return _socket.Read(lpBuffer, dwSize, lpAddrIn, dwTimeout);
  155. }
  156. DWORD Write(const LPBYTE lpBuffer, DWORD dwCount, const LPSOCKADDR lpAddrIn = NULL, DWORD dwTimeout = INFINITE)
  157. {
  158. return _socket.Write(lpBuffer, dwCount, lpAddrIn, dwTimeout);
  159. }
  160. const SocketBufferList& GetSocketList() const
  161. {
  162. // direct access! - use Lock/Unlock to protect
  163. return _sockets;
  164. }
  165. SocketBufferList& GetClientSocketList()
  166. {
  167. // direct access! - use Lock/Unlock to protect
  168. return _sockets;
  169. }
  170. bool Lock()
  171. {
  172. return _critSection.Lock();
  173. }
  174. bool Unlock()
  175. {
  176. return _critSection.Unlock();
  177. }
  178. void ResetConnectionList()
  179. {
  180. AutoThreadSection aSection(&_critSection);
  181. _sockets.clear();
  182. }
  183. size_t GetConnectionCount() //const
  184. {
  185. AutoThreadSection aSection(&_critSection);
  186. return _sockets.size();
  187. }
  188. void AddConnection(SOCKET sock)
  189. {
  190. AutoThreadSection aSection(&_critSection);
  191. _sockets.push_back( sock );
  192. }
  193. void RemoveConnection(SOCKET sock)
  194. {
  195. AutoThreadSection aSection(&_critSection);
  196. _sockets.remove( sock );
  197. LOG4C((LOG_NOTICE,"删除无效连接:%d",sock));
  198. }
  199. SocketIOBuffer* GetConnectionBuffer(SOCKET sock)
  200. {
  201. AutoThreadSection aSection(&_critSection);
  202. SocketBufferList::iterator iter = std::find(_sockets.begin(), _sockets.end(), sock);
  203. return ((iter != _sockets.end()) ? &(*iter) : NULL);
  204. }
  205. bool CloseConnection(SOCKET sock)
  206. {
  207. return CSocketHandle::ShutdownConnection( sock );
  208. LOG4C((LOG_NOTICE,"--删除无效连接:%d",sock));
  209. }
  210. void CloseAllConnections();
  211. bool StartServer(LPCTSTR pszHost, LPCTSTR pszServiceName, int nFamily, int nType, UINT uOptions = 0);
  212. void Terminate(DWORD dwTimeout = INFINITE);
  213. static bool IsConnectionDropped(DWORD dwError);
  214. ThreadSection *ReturnSection() { return &_critSection; }
  215. protected:
  216. void Run();
  217. void IoRun();
  218. bool AsyncRead(SocketIOBuffer* pBuffer);
  219. void OnIOComplete(DWORD dwError, SocketIOBuffer* pBuffer, DWORD cbTransferred, DWORD dwFlags);
  220. static DWORD WINAPI SocketServerProc(thisClass* _this);
  221. static DWORD WINAPI SocketServerIOProc(thisClass* _this);
  222. static void WINAPI CompletionRoutine(DWORD dwError, DWORD cbTransferred,
  223. LPWSAOVERLAPPED lpOverlapped, DWORD dwFlags);
  224. T* _pInterface;
  225. HANDLE _thread;
  226. DWORD _threadId;
  227. ThreadSection _critSection;
  228. CSocketHandle _socket;
  229. SocketBufferList _sockets;
  230. };
  231. template <typename T, size_t tBufferSize>
  232. void ASocketServerImpl<T, tBufferSize>::CloseAllConnections()
  233. {
  234. AutoThreadSection aSection(&_critSection);
  235. if ( !_sockets.empty() )
  236. {
  237. // NOTE(elaurentin): this function closes all connections but handles are kept inside of list
  238. // (socket handles are removed by the pooling thread)
  239. SocketBufferList::iterator iter;
  240. for(iter = _sockets.begin(); iter != _sockets.end(); ++iter)
  241. {
  242. CloseConnection( (*iter) );
  243. }
  244. }
  245. }
  246. template <typename T, size_t tBufferSize>
  247. bool ASocketServerImpl<T, tBufferSize>::StartServer(LPCTSTR pszHost, LPCTSTR pszServiceName, int nFamily, int nType, UINT uOptions)
  248. {
  249. // must be closed first...
  250. if ( IsOpen() ) return false;
  251. bool result = false;
  252. result = _socket.CreateSocket(pszHost, pszServiceName, nFamily, nType, uOptions);
  253. if ( result )
  254. {
  255. _thread = AtlCreateThread(SocketServerProc, this);
  256. if ( _thread == NULL )
  257. {
  258. DWORD dwError = GetLastError();
  259. _socket.Close();
  260. SetLastError(dwError);
  261. result = false;
  262. }
  263. }
  264. return result;
  265. }
  266. template <typename T, size_t tBufferSize>
  267. void ASocketServerImpl<T, tBufferSize>::Run()
  268. {
  269. _ASSERTE( _pInterface != NULL && "Need an interface to pass events");
  270. SOCKET sock = _socket.GetSocket();
  271. int type = _socket.GetSocketType();
  272. // Notification: OnThreadBegin
  273. if ( _pInterface != NULL ) {
  274. _pInterface->OnThreadBegin(*this);
  275. }
  276. if (type == SOCK_STREAM)
  277. {
  278. HANDLE ioThread = NULL;
  279. DWORD ioThreadId = 0L;
  280. ioThread = CreateThreadT(0, 0, SocketServerIOProc, this, 0, &ioThreadId);
  281. if ( ioThread == NULL )
  282. {
  283. DWORD dwError = GetLastError();
  284. if ( _pInterface != NULL ) {
  285. _pInterface->OnConnectionError(*this, dwError);
  286. }
  287. }
  288. // In TCP mode, use an I/O thread to process all requests
  289. while( _socket.IsOpen() )
  290. {
  291. SOCKET newSocket = CSocketHandle::WaitForConnection(sock);
  292. if (!_socket.IsOpen())
  293. break;
  294. if (!PostThreadMessage(ioThreadId, WM_ADD_CONNECTION, 0,
  295. static_cast<ULONG_PTR>(newSocket)))
  296. {
  297. // Notification: OnConnectionFailure
  298. if ( _pInterface != NULL ) {
  299. _pInterface->OnConnectionFailure(*this, newSocket);
  300. }
  301. }
  302. }
  303. // close all connections
  304. CloseAllConnections();
  305. // wait for io thread
  306. if ( ioThread != NULL )
  307. {
  308. PostThreadMessage(ioThreadId, WM_QUIT, 0, 0);
  309. WaitForSingleObject(ioThread, INFINITE);
  310. CloseHandle(ioThread);
  311. }
  312. ResetConnectionList();
  313. }
  314. else
  315. {
  316. // UDP mode - let's reuse our thread here
  317. try
  318. {
  319. SocketIOBuffer ioBuffer(_socket.GetSocket(), tBufferSize);
  320. AsyncRead( &ioBuffer );
  321. // Save our thread id so we can exit gracefully
  322. _threadId = GetCurrentThreadId();
  323. // Process UDP packets
  324. IoRun();
  325. } catch(std::bad_alloc&)
  326. { /* memory exception */
  327. if ( _pInterface != NULL )
  328. {
  329. _pInterface->OnConnectionError(*this, ERROR_NOT_ENOUGH_MEMORY);
  330. }
  331. }
  332. }
  333. // Notification: OnThreadExit
  334. if ( _pInterface != NULL ) {
  335. _pInterface->OnThreadExit(*this);
  336. }
  337. }
  338. template <typename T, size_t tBufferSize>
  339. void ASocketServerImpl<T, tBufferSize>::IoRun()
  340. {
  341. _ASSERTE( _pInterface != NULL && "Need an interface to pass events");
  342. MSG msg;
  343. ::PeekMessage(&msg, NULL, WM_USER, WM_USER, PM_NOREMOVE);
  344. // Notification: OnThreadLoopEnter
  345. if ( _pInterface != NULL ) {
  346. _pInterface->OnThreadLoopEnter(*this);
  347. }
  348. DWORD dwResult;
  349. while( (dwResult = MsgWaitForMultipleObjectsEx(0, NULL, INFINITE, QS_ALLEVENTS, MWMO_ALERTABLE)) != WAIT_FAILED)
  350. {
  351. msg.message = 0;
  352. PeekMessage(&msg, NULL, 0, 0, PM_REMOVE);
  353. // exit on WM_QUIT or main socket closed
  354. if ( msg.message == WM_QUIT || !_socket.IsOpen() )
  355. break;
  356. else if ( msg.message == WM_ADD_CONNECTION )
  357. {
  358. SOCKET sock = static_cast<SOCKET>(msg.lParam);
  359. AddConnection(sock);
  360. SocketIOBuffer* pBuffer = GetConnectionBuffer(sock);
  361. _ASSERTE( pBuffer != NULL );
  362. if ( pBuffer != NULL )
  363. {
  364. pBuffer->ReAlloc( tBufferSize );
  365. if (!AsyncRead(pBuffer))
  366. {
  367. // remove and close connection
  368. RemoveConnection( sock );//Jeff.wasn't remove at here;
  369. CloseConnection( sock );// Jeff.doesn't close socket here;
  370. }
  371. else
  372. {
  373. // Notification: OnAddConnection
  374. if ( _pInterface != NULL ) {
  375. _pInterface->OnAddConnection(*this, sock);
  376. }
  377. }
  378. }
  379. }
  380. }
  381. // Notification: OnThreadLoopLeave
  382. if ( _pInterface != NULL ) {
  383. _pInterface->OnThreadLoopLeave(*this);
  384. }
  385. }
  386. template <typename T, size_t tBufferSize>
  387. bool ASocketServerImpl<T, tBufferSize>::AsyncRead(SocketIOBuffer* pBuffer)
  388. {
  389. CSocketHandle sockHandle;
  390. DWORD dwRead;
  391. SocketIOBuffer& sbuf = (*pBuffer);
  392. SOCKET sock = static_cast<SOCKET>(sbuf);
  393. sockHandle.Attach( sock );
  394. int type = sockHandle.GetSocketType();
  395. LPWSAOVERLAPPED lpOverlapped = static_cast<LPWSAOVERLAPPED>(sbuf);
  396. lpOverlapped->hEvent = reinterpret_cast<HANDLE>(this);
  397. lpOverlapped->Pointer = reinterpret_cast<PVOID>(pBuffer);
  398. if (type == SOCK_STREAM) {
  399. // TCP - save current peer address
  400. sockHandle.GetPeerName( sbuf );
  401. dwRead = sockHandle.ReadEx(static_cast<LPBYTE>(sbuf), // buffer
  402. static_cast<DWORD>(sbuf.BufferSize()), // buffer size
  403. NULL, // sockaddr
  404. lpOverlapped, // overlapped
  405. thisClass::CompletionRoutine );
  406. } else {
  407. dwRead = sockHandle.ReadEx(static_cast<LPBYTE>(sbuf), // buffer
  408. static_cast<DWORD>(sbuf.BufferSize()), // buffer size
  409. static_cast<LPSOCKADDR>(sbuf), // sockaddr
  410. lpOverlapped, // overlapped
  411. thisClass::CompletionRoutine );
  412. }
  413. sockHandle.Detach();
  414. return ( dwRead != -1L );
  415. }
  416. template <typename T, size_t tBufferSize>
  417. void ASocketServerImpl<T, tBufferSize>::OnIOComplete(DWORD dwError, SocketIOBuffer* pBuffer, DWORD cbTransferred, DWORD /*dwFlags*/)
  418. {
  419. _ASSERTE( _pInterface != NULL && "Need an interface to pass events");
  420. _ASSERTE( pBuffer != NULL && "Invalid Buffer");
  421. if ( pBuffer != NULL )
  422. {
  423. CSocketHandle sockHandle;
  424. SOCKET sock = static_cast<SOCKET>(*pBuffer);
  425. sockHandle.Attach( sock );
  426. int type = sockHandle.GetSocketType();
  427. if ( dwError == NOERROR )
  428. {
  429. if (type == SOCK_STREAM && cbTransferred == 0L )
  430. {
  431. // connection broken
  432. if ( _pInterface != NULL ) {
  433. _pInterface->OnConnectionDropped(*this);
  434. }
  435. // remove connection
  436. RemoveConnection( sock );// Jeff.doesn't remove socket here;
  437. CloseConnection(sock);
  438. if ( _pInterface != NULL ) {
  439. // Notification: OnRemoveConnection
  440. _pInterface->OnRemoveConnection(*this, sock);
  441. }
  442. }
  443. else
  444. {
  445. // Notification: OnDataReceived
  446. if ( _pInterface != NULL ) {
  447. _pInterface->OnDataReceived(static_cast<LPWSAOVERLAPPED>(*pBuffer),
  448. static_cast<LPBYTE>(*pBuffer), // Data
  449. cbTransferred, // Number of bytes
  450. static_cast<SockAddrIn&>(*pBuffer));
  451. }
  452. // schedule another read for this socket
  453. AsyncRead( pBuffer );
  454. }
  455. }
  456. else
  457. {
  458. for ( ; _pInterface != NULL; )
  459. {
  460. if (IsConnectionDropped( dwError) )
  461. {
  462. // Notification: OnConnectionDropped
  463. if (type == SOCK_STREAM || (dwError == WSAENOTSOCK || dwError == WSAENETDOWN))
  464. //if (type == SOCK_STREAM && (dwError == WSAENOTSOCK || dwError == WSAENETDOWN))// Jeff.set.
  465. {
  466. // remove connection
  467. RemoveConnection( sock );// Jeff.doesn't remove socket here;
  468. CloseConnection(sock);
  469. if ( _pInterface != NULL ) {
  470. // Notification: OnRemoveConnection
  471. _pInterface->OnRemoveConnection(*this, sock);
  472. }
  473. _pInterface->OnConnectionDropped(*this);
  474. //_pInterface->OnConnectionError(*this, dwError); // Jeff.add
  475. type = -1; // don't schedule other request
  476. break;
  477. }
  478. }
  479. // Notification: OnConnectionError
  480. _pInterface->OnConnectionError(*this, dwError);
  481. break;
  482. }
  483. // Schedule read request
  484. if ((type == SOCK_STREAM || type == SOCK_DGRAM) && _socket.IsOpen() ) {
  485. AsyncRead( pBuffer );
  486. }
  487. }
  488. // Detach or Close this socket (TCP-mode only)
  489. if (type != SOCK_STREAM ||(type == SOCK_STREAM && cbTransferred != 0L) )
  490. {
  491. sockHandle.Detach();
  492. }
  493. }
  494. }
  495. template <typename T, size_t tBufferSize>
  496. void ASocketServerImpl<T, tBufferSize>::Terminate(DWORD dwTimeout /*= INFINITE*/)
  497. {
  498. _socket.Close();
  499. if ( _thread != NULL )
  500. {
  501. if ( _threadId != 0 ) {
  502. PostThreadMessage(_threadId, WM_QUIT, 0, 0);
  503. }
  504. if ( WaitForSingleObject(_thread, dwTimeout) == WAIT_TIMEOUT ) {
  505. TerminateThread(_thread, 1);
  506. }
  507. CloseHandle(_thread);
  508. _thread = NULL;
  509. _threadId = 0L;
  510. }
  511. }
  512. template <typename T, size_t tBufferSize>
  513. DWORD WINAPI ASocketServerImpl<T, tBufferSize>::SocketServerProc(thisClass* _this)
  514. {
  515. if ( _this != NULL )
  516. {
  517. _this->Run();
  518. }
  519. return 0;
  520. }
  521. template <typename T, size_t tBufferSize>
  522. DWORD WINAPI ASocketServerImpl<T, tBufferSize>::SocketServerIOProc(thisClass* _this)
  523. {
  524. if ( _this != NULL )
  525. {
  526. _this->IoRun();
  527. }
  528. return 0;
  529. }
  530. template <typename T, size_t tBufferSize>
  531. void WINAPI ASocketServerImpl<T, tBufferSize>::CompletionRoutine(DWORD dwError, DWORD cbTransferred,
  532. LPWSAOVERLAPPED lpOverlapped, DWORD dwFlags)
  533. {
  534. thisClass* _this = reinterpret_cast<thisClass*>( lpOverlapped->hEvent );
  535. if ( _this != NULL )
  536. {
  537. // Jeff有关Internal参数的处理,这里保存的是overlapped关于I/O请求的错误码=dwError
  538. if(dwError != 0)LOG4C((LOG_NOTICE,"%d",dwError));
  539. SocketIOBuffer* pBuffer = reinterpret_cast<SocketIOBuffer*>(lpOverlapped->Pointer);
  540. _this->OnIOComplete(dwError, pBuffer, cbTransferred, dwFlags);
  541. }
  542. }
  543. template <typename T, size_t tBufferSize>
  544. bool ASocketServerImpl<T, tBufferSize>::IsConnectionDropped(DWORD dwError)
  545. {
  546. // see: winerror.h for definition
  547. switch( dwError )
  548. {
  549. case WSAENOTSOCK: // 不是套接字;
  550. case WSAENETDOWN: // A socket operation encountered a dead network.
  551. case WSAENETUNREACH:// A socket operation was attempted to an unreachable network.
  552. case WSAENETRESET:// The connection has been broken due to keep-alive activity detecting a failure while the operation was in progress.
  553. case WSAECONNABORTED:
  554. case WSAECONNRESET:// An existing connection was forcibly closed by the remote host.
  555. case WSAESHUTDOWN:
  556. case WSAEHOSTDOWN:
  557. case WSAEHOSTUNREACH:
  558. return true;
  559. default:
  560. break;
  561. }
  562. return false;
  563. }
  564. #endif //ASYNCSOCKETSERVERIMPL_H