SocketClientImpl.h 6.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260
  1. #ifndef SOCKETCLIENTIMPL_H
  2. #define SOCKETCLIENTIMPL_H
  3. #pragma once
  4. #pragma warning(push)
  5. #pragma warning(disable:4995)
  6. #include <vector>
  7. #pragma warning(pop)
  8. #include "SocketHandle.h"
  9. /**
  10. * ISocketClientHandler
  11. * Event handler that SocketClientImpl<T> must implement
  12. * This class is not required, you can do the same thing as long your class exposes these functions.
  13. * (These are not pure to save you some typing)
  14. */
  15. class ISocketClientHandler
  16. {
  17. public:
  18. virtual void OnThreadBegin(CSocketHandle* ) {}
  19. virtual void OnThreadExit(CSocketHandle* ) {}
  20. virtual void OnDataReceived(CSocketHandle* , const BYTE* , DWORD , const SockAddrIn& ) {}
  21. virtual void OnConnectionDropped(CSocketHandle* ) {}
  22. virtual void OnConnectionError(CSocketHandle* , DWORD ) {}
  23. };
  24. /**
  25. * SocketClientImpl<T, tBufferSize>
  26. * Because <typename T> may refer to any class of your choosing,
  27. * Client Communication wrapper
  28. */
  29. template <typename T, size_t tBufferSize = 2048>
  30. class SocketClientImpl
  31. {
  32. typedef SocketClientImpl<T, tBufferSize> thisClass;
  33. public:
  34. SocketClientImpl()
  35. : _pInterface(0)
  36. , _thread(0)
  37. {
  38. }
  39. void SetInterface(T* pInterface)
  40. {
  41. ::InterlockedExchangePointer(reinterpret_cast<void**>(&_pInterface), pInterface);
  42. }
  43. operator CSocketHandle*() throw()
  44. {
  45. return( &_socket );
  46. }
  47. CSocketHandle* operator->() throw()
  48. {
  49. return( &_socket );
  50. }
  51. bool IsOpen() const
  52. {
  53. return _socket.IsOpen();
  54. }
  55. bool CreateSocket(LPCTSTR pszHost, LPCTSTR pszServiceName, int nFamily, int nType, UINT uOptions = 0)
  56. {
  57. return _socket.CreateSocket(pszHost, pszServiceName, nFamily, nType, uOptions);
  58. }
  59. bool ConnectTo(LPCTSTR pszHostName, LPCTSTR pszRemote, LPCTSTR pszServiceName, int nFamily, int nType)
  60. {
  61. return _socket.ConnectTo(pszHostName, pszRemote, pszServiceName, nFamily, nType);
  62. }
  63. void Close()
  64. {
  65. _socket.Close();
  66. }
  67. DWORD Read(LPBYTE lpBuffer, DWORD dwSize, LPSOCKADDR lpAddrIn = NULL, DWORD dwTimeout = INFINITE)
  68. {
  69. return _socket.Read(lpBuffer, dwSize, lpAddrIn, dwTimeout);
  70. }
  71. DWORD Write(const LPBYTE lpBuffer, DWORD dwCount, const LPSOCKADDR lpAddrIn = NULL, DWORD dwTimeout = INFINITE)
  72. {
  73. return _socket.Write(lpBuffer, dwCount, lpAddrIn, dwTimeout);
  74. }
  75. bool StartClient(LPCTSTR pszHost, LPCTSTR pszRemote, LPCTSTR pszServiceName, int nFamily, int nType, UINT uOptions = 0);
  76. void Terminate(DWORD dwTimeout = INFINITE);
  77. static bool IsConnectionDropped(DWORD dwError);
  78. protected:
  79. void Run();
  80. static DWORD WINAPI SocketClientProc(thisClass* _this);
  81. T* _pInterface;
  82. HANDLE _thread;
  83. CSocketHandle _socket;
  84. };
  85. template <typename T, size_t tBufferSize>
  86. bool SocketClientImpl<T, tBufferSize>::StartClient(LPCTSTR pszHost, LPCTSTR pszRemote, LPCTSTR pszServiceName, int nFamily, int nType, UINT uOptions = 0)
  87. {
  88. // must be closed first...
  89. if ( IsOpen() )
  90. {
  91. LOG4C((LOG_NOTICE, "Á¬½Óʧ°Ü£¬Ô­Òò£ºSocketClientImpl : IsOpen() "));
  92. return false;
  93. }
  94. bool result = false;
  95. if ( nType == SOCK_STREAM )
  96. {
  97. result = _socket.ConnectTo(pszHost, pszRemote, pszServiceName, nFamily, nType); // TCP
  98. }
  99. else
  100. {
  101. // let provider select a port for us
  102. result = _socket.CreateSocket(pszHost, TEXT("0"), nFamily, nType, uOptions); // UDP
  103. }
  104. if ( result )
  105. {
  106. _thread = AtlCreateThread(SocketClientProc, this);
  107. if ( _thread == NULL )
  108. {
  109. DWORD dwError = GetLastError();
  110. _socket.Close();
  111. SetLastError(dwError);
  112. result = false;
  113. }
  114. }
  115. return result;
  116. }
  117. template <typename T, size_t tBufferSize>
  118. void SocketClientImpl<T, tBufferSize>::Run()
  119. {
  120. SockAddrIn addrIn;
  121. std::vector<unsigned char> data;
  122. data.resize( tBufferSize );
  123. DWORD dwRead;
  124. DWORD dwError;
  125. _ASSERTE( _pInterface != NULL && "Need an interface to pass events");
  126. // Notification: OnThreadBegin
  127. if ( _pInterface != NULL ) {
  128. _pInterface->OnThreadBegin(*this);
  129. }
  130. int type = _socket.GetSocketType();
  131. if (type == SOCK_STREAM) {
  132. _socket.GetPeerName( addrIn );
  133. }
  134. while ( _socket.IsOpen() )
  135. {
  136. if (type == SOCK_STREAM)
  137. {
  138. dwRead = _socket.Read(&data[0], tBufferSize, NULL, INFINITE);
  139. }
  140. else
  141. {
  142. dwRead = _socket.Read(&data[0], tBufferSize, addrIn, INFINITE);
  143. }
  144. if ( (dwRead != -1L) && (dwRead > 0))
  145. {
  146. // Notification: OnDataReceived
  147. if ( _pInterface != NULL ) {
  148. _pInterface->OnDataReceived(*this, &data[0], dwRead, addrIn);
  149. }
  150. }
  151. else if (type == SOCK_STREAM && dwRead == 0L )
  152. {
  153. // connection broken
  154. if ( _pInterface != NULL )
  155. {
  156. _pInterface->OnConnectionDropped(*this);
  157. }
  158. break;
  159. }
  160. else if ( dwRead == -1L )
  161. {
  162. dwError = GetLastError();
  163. if ( _pInterface != NULL )
  164. {
  165. if (IsConnectionDropped( dwError) ) {
  166. // Notification: OnConnectionDropped
  167. if (type == SOCK_STREAM || (dwError == WSAENOTSOCK || dwError == WSAENETDOWN))
  168. {
  169. _pInterface->OnConnectionDropped(*this);
  170. break;
  171. }
  172. }
  173. // Notification: OnConnectionError
  174. _pInterface->OnConnectionError(*this, dwError);
  175. }
  176. else {
  177. break;
  178. }
  179. }
  180. }
  181. data.clear();
  182. // Notification: OnThreadExit
  183. if ( _pInterface != NULL ) {
  184. _pInterface->OnThreadExit(*this);
  185. }
  186. }
  187. template <typename T, size_t tBufferSize>
  188. void SocketClientImpl<T, tBufferSize>::Terminate(DWORD dwTimeout /*= INFINITE*/)
  189. {
  190. _socket.Close();
  191. if ( _thread != NULL )
  192. {
  193. if ( WaitForSingleObject(_thread, dwTimeout) == WAIT_TIMEOUT ) {
  194. TerminateThread(_thread, 1);
  195. }
  196. CloseHandle(_thread);
  197. _thread = NULL;
  198. }
  199. }
  200. template <typename T, size_t tBufferSize>
  201. DWORD WINAPI SocketClientImpl<T, tBufferSize>::SocketClientProc(thisClass* _this)
  202. {
  203. if ( _this != NULL )
  204. {
  205. _this->Run();
  206. }
  207. return 0;
  208. }
  209. template <typename T, size_t tBufferSize>
  210. bool SocketClientImpl<T, tBufferSize>::IsConnectionDropped(DWORD dwError)
  211. {
  212. // see: winerror.h for definition
  213. switch( dwError )
  214. {
  215. case WSAENOTSOCK:
  216. case WSAENETDOWN:
  217. case WSAENETUNREACH:
  218. case WSAENETRESET:
  219. case WSAECONNABORTED:
  220. case WSAECONNRESET:
  221. case WSAESHUTDOWN:
  222. case WSAEHOSTDOWN:
  223. case WSAEHOSTUNREACH:
  224. return true;
  225. default:
  226. break;
  227. }
  228. return false;
  229. }
  230. #endif //SOCKETCLIENTIMPL_H