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

模拟服务器

开发平台:

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