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

模拟服务器

开发平台:

C/C++

  1. #include "GameClient.h"
  2. //[ Include in ...ESClient
  3. #include "ESClientUtils.h"
  4. #include "ESClientWin32Exception.h"
  5. #include "ESClientSocket.h"
  6. #include "ESClientException.h"
  7. //]
  8. //[ Include in ...Protocol
  9. #include "ProtocolProtocol.h"
  10. //]
  11. /*
  12.  * Using directives
  13.  */
  14. using OnlineGameLib::Win32::CIOBuffer;
  15. using OnlineGameLib::Win32::Output;
  16. using OnlineGameLib::Win32::OutPutInfo;
  17. using OnlineGameLib::Win32::ToString;
  18. using OnlineGameLib::Win32::_tstring;
  19. using OnlineGameLib::Win32::CException;
  20. using OnlineGameLib::Win32::CWin32Exception;
  21. using OnlineGameLib::Win32::CSocket;
  22. using OnlineGameLib::Win32::DumpData;
  23. CGameClient::CGameClient(
  24. const OnlineGameLib::Win32::_tstring &addressToConnectServer,
  25. unsigned short portToConnectServer,
  26. size_t maxFreeBuffers,
  27. size_t bufferSize /* = 1024 */
  28. )
  29. : OnlineGameLib::Win32::CSocketClient(addressToConnectServer, portToConnectServer, maxFreeBuffers, bufferSize),
  30. m_pRecvBuf( NULL ),
  31. m_dwRecvSize( 0 )
  32. {
  33. m_hHasRecvdata = CreateEvent(
  34. NULL, // no security attributes
  35.         TRUE, // manual-reset event
  36.         FALSE, // initial state is signaled
  37.         "ReadEvent" // object name
  38. );
  39. }
  40. CGameClient::CGameClient(
  41. size_t maxFreeBuffers,
  42. size_t bufferSize /* = 1024 */
  43. )
  44. : OnlineGameLib::Win32::CSocketClient(maxFreeBuffers, bufferSize),
  45. m_pRecvBuf( NULL ),
  46. m_dwRecvSize( 0 )
  47. {
  48. m_hHasRecvdata = CreateEvent(
  49. NULL, // no security attributes
  50.         TRUE, // manual-reset event
  51.         FALSE, // initial state is signaled
  52.         "ReadEvent" // object name
  53. );
  54. }
  55. CGameClient::~CGameClient()
  56. {
  57. try
  58. {
  59. ReleaseBuffers();
  60. }
  61. catch(...)
  62. {
  63. }
  64. }
  65. SOCKET CGameClient::CreateConnectionSocket( 
  66.   const OnlineGameLib::Win32::_tstring &addressToConnectServer,
  67.   unsigned short port)
  68. {
  69. SOCKET s = ::WSASocket( AF_INET, SOCK_STREAM, IPPROTO_IP, NULL, 0, 0 );
  70. if ( INVALID_SOCKET == s )
  71. {
  72. throw CWin32Exception( _T("CSocket::CreateListeningSocket()"), ::WSAGetLastError() );
  73. }
  74. CSocket connectionSocket( s );
  75. CSocket::InternetAddress localAddress( addressToConnectServer, port );
  76. connectionSocket.Connect( localAddress );
  77. return connectionSocket.Detatch();
  78. }
  79. void CGameClient::OnStartConnections()
  80. {
  81. Output( _T("OnStartConnections") );
  82. }
  83. void CGameClient::OnStopConnections()
  84. {
  85. Output( _T("OnStopConnections") );
  86. }
  87. void CGameClient::OnShutdownInitiated()
  88. {
  89. Output( _T("OnShutdownInitiated") );
  90. }
  91. void CGameClient::OnShutdownComplete()
  92. {
  93. Output( _T("OnShutdownComplete") );
  94. }
  95. void CGameClient::OnError( const OnlineGameLib::Win32::_tstring &message )
  96. {
  97. Output( _T("OnError - ") + message );
  98. }
  99. void CGameClient::OnConnect()
  100. {
  101. Output( _T("OnConnect") );
  102. }
  103. void CGameClient::OnClose()
  104. {
  105. Output( _T("OnClose") );
  106. }
  107. void CGameClient::ReadCompleted( OnlineGameLib::Win32::CIOBuffer *pBuffer )
  108. {
  109. try
  110. {
  111. pBuffer = ProcessDataStream( pBuffer );
  112. }
  113. catch(const CException &e)
  114. {
  115. Output( _T("ReadCompleted - Exception - ") + e.GetWhere() + _T(" - ") + e.GetMessage() );
  116. StopConnections();
  117. }
  118. catch(...)
  119. {
  120. Output( _T("ReadCompleted - Unexpected exception") );
  121. StopConnections();
  122. }
  123. }
  124. void CGameClient::ProcessCommand( const OnlineGameLib::Win32::CIOBuffer *pBuffer)
  125. {
  126. const BYTE *pPackData = pBuffer->GetBuffer();
  127. const size_t used = pBuffer->GetUsed();
  128. bool ok = false;
  129. WORD wDataLen = 0;
  130. PACK_HEADER ph = {0};
  131. if ( used > PACK_HEADER_LEN )
  132. {
  133. memcpy( &ph, pPackData, PACK_HEADER_LEN );
  134. wDataLen = ph.wDataLen;
  135. ok = true;
  136. }
  137. if ( ok )
  138. {
  139. const BYTE *pData = pPackData + PACK_HEADER_LEN;
  140. const size_t datalength = wDataLen;
  141. /*
  142.  * TODO : Process data receive from server
  143.  */
  144. // ==================== BEGIN =======================
  145. Output( _T("Package[length:") + ToString( wDataLen ) + _T("]n") + DumpData( pData, datalength, 40 ) );
  146. m_pRecvBuf = pData;
  147. m_dwRecvSize = datalength;
  148. SetEvent( m_hHasRecvdata );
  149. // ====================  END  =======================
  150. }
  151. else
  152. {
  153. Output( "found error and close this connection!" );
  154. StopConnections();
  155. }
  156. }
  157. size_t CGameClient::GetMinimumMessageSize() const
  158. {
  159. /*
  160.  * The smallest possible package we accept is pack-header
  161.  * once we have this many bytes we can start with try and work out
  162.  * what we have...
  163.  */
  164. return PACK_HEADER_LEN;
  165. }
  166. size_t CGameClient::GetMessageSize( 
  167. const OnlineGameLib::Win32::CIOBuffer *pBuffer ) const
  168. {
  169. const BYTE *pData = pBuffer->GetBuffer();
  170. const size_t used = pBuffer->GetUsed();
  171. PACK_HEADER ph = {0};
  172. /*
  173.  * First, verify the flag of a message
  174.  */
  175. if ( used > PACK_HEADER_LEN )
  176. {
  177. memcpy( &ph, pData, PACK_HEADER_LEN );
  178. if ( PACK_BEGIN_FLAG == ph.cPackBeginFlag && 
  179.  PACK_END_FLAG == ph.cPackEndFlag )
  180. {
  181. WORD wCRC = MAKE_CRC_DATE( PACK_BEGIN_FLAG, PACK_END_FLAG, ph.wDataLen );
  182. if ( ph.wCRCData == wCRC )
  183. {
  184. return ph.wDataLen + PACK_HEADER_LEN;
  185. }
  186. }
  187. }
  188. return 0;
  189. }
  190. CIOBuffer *CGameClient::ProcessDataStream( OnlineGameLib::Win32::CIOBuffer *pBuffer)
  191. {
  192. bool done;
  193. // DEBUG_ONLY( Output( _T("ProcessDataStream:n") + DumpData( pBuffer->GetBuffer(), pBuffer->GetUsed(), 40 ) ) );
  194. do
  195. {
  196. done = true;
  197. const size_t used = pBuffer->GetUsed();
  198. if ( used >= GetMinimumMessageSize() )
  199. {
  200. const size_t messageSize = GetMessageSize( pBuffer );
  201. if ( messageSize == 0 )
  202. {
  203. /*
  204.  * havent got a complete message yet.
  205.  * we null terminate our messages in the buffer, so we need to reserve
  206.  * a byte of the buffer for this purpose...
  207.  */
  208. if ( used == ( pBuffer->GetSize() - 1 ) )
  209. {
  210. Output( _T("Too much data!") );
  211. /*
  212.  * Write this message and then shutdown the sending side of the socket.
  213.  */
  214. Output( "found error and close this connection!" );
  215. StopConnections();
  216. /*
  217.  * throw the rubbish away
  218.  */
  219. pBuffer->Empty();
  220. done = true;
  221. }
  222. }
  223. else if ( used == messageSize )
  224. {
  225. Output( _T("Got complete, distinct, message") );
  226. /*
  227.  * we have a whole, distinct, message
  228.  */
  229. pBuffer->AddData(0);   // null terminate the command string;
  230. ProcessCommand( pBuffer );
  231. pBuffer->Empty();
  232. done = true;
  233. }
  234. else if (used > messageSize)
  235. {
  236. Output(_T("Got message plus extra data"));
  237. /*
  238.  * we have a message, plus some more data
  239.  * 
  240.  * allocate a new buffer, copy the extra data into it and try again...
  241.  */
  242. CIOBuffer *pMessage = pBuffer->SplitBuffer( messageSize );
  243. pMessage->AddData(0);   // null terminate the command string;
  244. ProcessCommand( pMessage );
  245. pMessage->Release();
  246. /*
  247.  * loop again, we may have another complete message in there...
  248.  */
  249. done = false;
  250. }
  251. }
  252. }
  253. while ( !done );
  254. /*
  255.  * not enough data in the buffer, reissue a read into the same buffer to collect more data
  256.  */
  257. return pBuffer;
  258. }
  259. void CGameClient::PreWrite( 
  260. OnlineGameLib::Win32::CIOBuffer *pBuffer, 
  261. const char *pData, 
  262. size_t dataLength )
  263. {
  264. /*
  265.  * TODO : You can change protocol that it is used to split package
  266.  */
  267. if ( pBuffer && dataLength > 0 )
  268. {
  269. PACK_HEADER ph = {0};
  270. ph.cPackBeginFlag = PACK_BEGIN_FLAG;
  271. ph.cPackEndFlag = PACK_END_FLAG;
  272. ph.wDataLen = dataLength;
  273. ph.wCRCData = MAKE_CRC_DATE( PACK_BEGIN_FLAG, PACK_END_FLAG, dataLength );
  274. pBuffer->AddData( reinterpret_cast<const char *>(&ph), PACK_HEADER_LEN );
  275. }
  276. }