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