SocketClient.cpp
上传用户:dzyhzl
上传日期:2019-04-29
资源大小:56270k
文件大小:7k
源码类别:

模拟服务器

开发平台:

C/C++

  1. #include "SocketClient.h"
  2. #include "Win32Exception.h"
  3. #include "Utils.h"
  4. #include <vector>
  5. #pragma comment(lib, "ws2_32.lib")
  6. /*
  7.  * Link options and warning
  8.  */
  9. #pragma message( "NOTE : --------------------OnlineGameLib [Client] : Announcement--------------------" )
  10. #pragma message( "NOTE : The lib be used for socket communicate that it is base on" )
  11. #pragma message( "NOTE : Windows 95 and Windows NT 3.51 and later" )
  12. #pragma message( "NOTE :" )
  13. #pragma message( "NOTE : liupeng xishanju.zhuhai.china 2003.1" )
  14. #pragma message( "NOTE : -----------------------------------------------------------------------------" )
  15. using std::vector;
  16. /*
  17.  * namespace OnlineGameLib::Win32
  18.  */
  19. namespace OnlineGameLib {
  20. namespace Win32 {
  21. CSocketClient::CSocketClient(
  22. const _tstring &addressToConnectServer,
  23. unsigned short portToConnectServer,
  24. size_t maxFreeBuffers,
  25. size_t bufferSize /* = 1024 */
  26. )
  27.   : CIOBuffer::Allocator(bufferSize, maxFreeBuffers),
  28. m_address(addressToConnectServer),
  29. m_port(portToConnectServer),
  30. m_connectSocket(INVALID_SOCKET)
  31. {
  32. }
  33. CSocketClient::CSocketClient(
  34. size_t maxFreeBuffers,
  35. size_t bufferSize /* = 1024 */
  36. )
  37. : CIOBuffer::Allocator(bufferSize, maxFreeBuffers),
  38. m_port(0),
  39. m_connectSocket(INVALID_SOCKET)
  40. {
  41. }
  42. void CSocketClient::ConnectTo(
  43.    const _tstring &addressToConnectServer,
  44.    unsigned short portToConnectServer
  45.    )
  46. {
  47. m_address = addressToConnectServer;
  48. m_port = portToConnectServer;
  49. }
  50. CSocketClient::~CSocketClient()
  51. {
  52. try
  53. {
  54. StopConnections();
  55. }
  56. catch(...)
  57. {
  58. }
  59. }
  60. void CSocketClient::StartConnections()
  61. {
  62. if ( INVALID_SOCKET == m_connectSocket )
  63. {
  64. /*
  65.  * Call to unqualified virtual function
  66.  */
  67. OnStartConnections();
  68. /*
  69.  * call to unqualified virtual function
  70.  */
  71. m_connectSocket = CreateConnectionSocket( m_address, m_port );
  72. m_eventSelect.AssociateEvent( m_connectSocket, FD_CONNECT | FD_CLOSE | FD_READ );
  73. m_successConnectionsEvent.Set();
  74. }
  75. }
  76. void CSocketClient::StopConnections()
  77. {
  78. if ( INVALID_SOCKET != m_connectSocket )
  79. {
  80. m_successConnectionsEvent.Reset();
  81. if ( 0 != ::closesocket( m_connectSocket ) )
  82. {
  83. /*
  84.  * Call to unqualified virtual function
  85.  */
  86. OnError( _T("CSocketClient::StopAcceptingConnections() - closesocket - ") + GetLastErrorMessage( ::WSAGetLastError() ) );
  87. }
  88. m_connectSocket = INVALID_SOCKET;
  89. /*
  90.  * Call to unqualified virtual function
  91.  */
  92. OnStopConnections();
  93. }
  94. }
  95. void CSocketClient::InitiateShutdown()
  96. {
  97. /*
  98.  * Signal that the dispatch thread should shut down all worker threads and then exit
  99.  */
  100. StopConnections();
  101. m_shutdownEvent.Set();
  102. /*
  103.  * Call to unqualified virtual function
  104.  */
  105. OnShutdownInitiated();
  106. }
  107. void CSocketClient::WaitForShutdownToComplete()
  108. {
  109. /*
  110.  * If we havent already started a shut down, do so...
  111.  */
  112. InitiateShutdown();
  113. Wait();
  114. }
  115. int CSocketClient::Run()
  116. {
  117. try
  118. {
  119. HANDLE handlesToWaitFor[2];
  120. handlesToWaitFor[0] = m_shutdownEvent.GetEvent();
  121. handlesToWaitFor[1] = m_successConnectionsEvent.GetEvent();
  122. while ( !m_shutdownEvent.Wait( 0 ) )
  123. {
  124. DWORD waitResult = ::WaitForMultipleObjects( 2, handlesToWaitFor, false, INFINITE );
  125. if ( waitResult == WAIT_OBJECT_0 )
  126. {
  127. /*
  128.  * Time to shutdown
  129.  */
  130. break;
  131. }
  132. else if ( waitResult == WAIT_OBJECT_0 + 1 )
  133. {
  134. /*
  135.  * Allocate a buffer for required read
  136.  */
  137. CIOBuffer *pReadContext = Allocate();
  138. while ( !m_shutdownEvent.Wait( 0 ) && m_successConnectionsEvent.Wait( 0 ) )
  139. {
  140. if ( m_eventSelect.WaitForEnumEvent( m_connectSocket, 1000 ) )
  141. {
  142. /*
  143.  * Find some events and process it
  144.  */
  145. /*
  146.  * A event to connect
  147.  */
  148. if ( m_eventSelect.IsConnect() )
  149. {
  150. OnConnect();
  151. }
  152. /*
  153.  * A event to close
  154.  */
  155. if ( m_eventSelect.IsClose() )
  156. {
  157. OnClose();
  158. }
  159. /*
  160.  * A event to read
  161.  */
  162. if ( m_eventSelect.IsRead() )
  163. {
  164. OnRead( pReadContext );
  165. }
  166. /*
  167.  * A event to write
  168.  */
  169. if ( m_eventSelect.IsWrite() )
  170. {
  171. OnWrite();
  172. }
  173. }
  174. } // while (...
  175. pReadContext->Release();
  176. }
  177. else
  178. {
  179. /*
  180.  * Call to unqualified virtual function
  181.  */
  182. OnError( _T("CSocketClient::Run() - WaitForMultipleObjects: ") + GetLastErrorMessage( ::GetLastError() ) );
  183. }
  184. } // while ( ... 
  185. }
  186. catch( const CException &e )
  187. {
  188. /*
  189.  * Call to unqualified virtual function
  190.  */
  191. OnError( _T("CSocketClient::Run() - Exception: ") + e.GetWhere() + _T(" - ") + e.GetMessage() );
  192. }
  193. catch(...)
  194. {
  195. /*
  196.  * Call to unqualified virtual function
  197.  */
  198. OnError( _T("CSocketClient::Run() - Unexpected exception") );
  199. }
  200. /*
  201.  * Call to unqualified virtual function
  202.  */
  203. OnShutdownComplete();
  204. return 0;
  205. }
  206. void CSocketClient::ReleaseBuffers()
  207. {
  208. Flush();
  209. }
  210. void CSocketClient::OnError( const _tstring &message )
  211. {
  212. Output( message );
  213. }
  214. void CSocketClient::OnRead( CIOBuffer *pBuffer )
  215. {
  216. /*
  217.  * Determine the amount of data that can be read atomically from socket s
  218.  *
  219.  * ::WSAIoctl( s, FIONREAD, ...
  220.  */
  221. DWORD dwNumBytes = 0;
  222. DWORD dwFlags = 0;
  223. pBuffer->SetupRead();
  224. if ( SOCKET_ERROR == ::WSARecv(
  225. m_connectSocket,
  226. pBuffer->GetWSABUF(), 
  227. 1,
  228. &dwNumBytes, 
  229. &dwFlags,
  230. pBuffer,
  231. NULL ) )
  232. {
  233. DWORD lastError = ::WSAGetLastError();
  234. if ( ERROR_IO_PENDING != lastError )
  235. {
  236. Output( _T("CSocketClient::OnRead() - WSARecv: ") + GetLastErrorMessage( lastError ) );
  237. if ( lastError == WSAECONNABORTED || 
  238. lastError == WSAECONNRESET ||
  239. lastError == WSAEDISCON)
  240. {
  241. StopConnections();
  242. }
  243. }
  244. }
  245. else
  246. {
  247. pBuffer->Use( dwNumBytes );
  248. ReadCompleted( pBuffer );
  249. }
  250. }
  251. void CSocketClient::OnWrite()
  252. {
  253. }
  254. void CSocketClient::Write( const char *pData, size_t dataLength )
  255. {
  256. if ( INVALID_SOCKET != m_connectSocket &&
  257. dataLength > 0 &&
  258. pData )
  259. {
  260. CIOBuffer *pBuffer = Allocate();
  261. /*
  262.  * Call to unqualified virtual function
  263.  */
  264. PreWrite( pBuffer, pData, dataLength );
  265. pBuffer->AddData( pData, dataLength );
  266. /*
  267.  * Begin to send data
  268.  */
  269. pBuffer->SetupWrite();
  270. DWORD dwFlags = 0;
  271. DWORD dwSendNumBytes = 0;
  272. if ( SOCKET_ERROR == ::WSASend(
  273. m_connectSocket,
  274. pBuffer->GetWSABUF(), 
  275. 1, 
  276. &dwSendNumBytes,
  277. dwFlags,
  278. pBuffer, 
  279. NULL) )
  280. {
  281. DWORD lastError = ::WSAGetLastError();
  282. if ( ERROR_IO_PENDING != lastError )
  283. {
  284. Output( _T("CSocketClient::Write() - WSASend: ") + GetLastErrorMessage( lastError ) );
  285. if ( lastError == WSAECONNABORTED || 
  286. lastError == WSAECONNRESET ||
  287. lastError == WSAEDISCON)
  288. {
  289. StopConnections();
  290. }
  291. }
  292. }
  293. if ( pBuffer->GetUsed() != pBuffer->GetWSABUF()->len )
  294. {
  295. /*
  296.  * Call to unqualified virtual function
  297.  */
  298. //OnError(_T("CSocketClient::WriteCompleted - Socket write where not all data was written"));
  299. }
  300. pBuffer->Release();
  301. }
  302. }
  303. } // End of namespace OnlineGameLib
  304. } // End of namespace Win32