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

模拟服务器

开发平台:

C/C++

  1. #include "JXClient.h"
  2. #include <assert.h>
  3. //[ Include in ...IPCPServer
  4. #include "IOCPServerException.h"
  5. #include "IOCPServerUtils.h"
  6. #include "IOCPServerManualResetEvent.h"
  7. //]
  8. #include "Protocol.h"
  9. #include "GameClient.h"
  10. using OnlineGameLib::Win32::_tstring;
  11. using OnlineGameLib::Win32::CException;
  12. using OnlineGameLib::Win32::Output;
  13. using OnlineGameLib::Win32::CManualResetEvent;
  14. using OnlineGameLib::Win32::GetTimeStamp;
  15. using OnlineGameLib::Win32::OutPutInfo;
  16. using OnlineGameLib::Win32::ToString;
  17. using OnlineGameLib::Win32::CCriticalSection;
  18. using OnlineGameLib::Win32::DumpData;
  19. static CGameClient g_theJXClient( MAX_BUFFER_KEEPINPOOL, EXTEND_BUFFER_SIZE );
  20. static CConnectManager g_theManager( MAX_BUFFER_KEEPINPOOL, EXTEND_BUFFER_SIZE );
  21. CConnectManager::CConnectManager(
  22. size_t maxFreeBuffers, 
  23. size_t bufferSize /*1024*/ )
  24. : OnlineGameLib::Win32::CIOBuffer::Allocator(bufferSize, maxFreeBuffers),
  25. m_pfnCallbackClientEvent(NULL)
  26. {
  27. m_pReadBuffer = Allocate();
  28. m_pRecvBuffer = Allocate();
  29. }
  30. CConnectManager::~CConnectManager()
  31. {
  32. m_pReadBuffer->Release();
  33. m_pRecvBuffer->Release();
  34. try
  35. {
  36. Flush();
  37. }
  38. catch(...)
  39. {
  40. }
  41. }
  42. void CConnectManager::ConnectServer()
  43. {
  44. if ( m_pfnCallbackClientEvent )
  45. {
  46. m_pfnCallbackClientEvent( SERVER_CONNECT_CREATE );
  47. }
  48. }
  49. void CConnectManager::DisConnetServer()
  50. {
  51. if ( m_pfnCallbackClientEvent )
  52. {
  53. m_pfnCallbackClientEvent( SERVER_CONNECT_CLOSE );
  54. }
  55. }
  56. void CConnectManager::RecvFromServer( const char *pData, size_t dataLength )
  57. {
  58. CCriticalSection::Owner locker( m_csReadAction );
  59. m_pRecvBuffer->AddData( pData, dataLength );
  60. }
  61. const char *CConnectManager::GetFromClient( size_t &dataLength )
  62. {
  63. CCriticalSection::Owner locker( m_csReadAction );
  64. m_pReadBuffer->Empty();
  65. m_pRecvBuffer = ProcessDataStream( m_pRecvBuffer );
  66. const BYTE *pPackData = m_pReadBuffer->GetBuffer();
  67. dataLength = m_pReadBuffer->GetUsed();
  68. //[
  69. #ifdef NETWORK_DEBUG
  70. if ( dataLength > 0 )
  71. {
  72. static const int sc_nFlagLen = sizeof(DWORD) * 2 + PACK_HEADER_LEN + sizeof(BYTE);
  73. assert( dataLength > sc_nFlagLen && "Get error buffer from server!" );
  74. dataLength -= sc_nFlagLen;
  75. }
  76. #endif //NETWORK_DEBUG
  77. //]
  78. return reinterpret_cast<const char*>( pPackData );
  79. }
  80. void CConnectManager::ProcessCommand( const OnlineGameLib::Win32::CIOBuffer *pBuffer)
  81. {
  82. const BYTE *pPackData = pBuffer->GetBuffer();
  83. const size_t used = pBuffer->GetUsed();
  84. bool ok = false;
  85. WORD wDataLen = 0;
  86. PACK_HEADER ph = {0};
  87. if ( used > PACK_HEADER_LEN )
  88. {
  89. memcpy( &ph, pPackData, PACK_HEADER_LEN );
  90. wDataLen = ph.wDataLen;
  91. ok = true;
  92. }
  93. if ( ok )
  94. {
  95. const BYTE *pData = pPackData + PACK_HEADER_LEN;
  96. const size_t datalength = wDataLen;
  97. /*
  98.  * TODO : Process data receive from server
  99.  */
  100. //Output( _T("Get a package[length:") + ToString( wDataLen ) + _T("]n") + DumpData( pData, datalength, 50 ) );
  101. m_pReadBuffer->AddData( pData, datalength );
  102. }
  103. else
  104. {
  105. Output( "found error and close this connection!" );
  106. Shutdown();
  107. }
  108. }
  109. size_t CConnectManager::GetMinimumMessageSize() const
  110. {
  111. /*
  112.  * The smallest possible package we accept is pack-header
  113.  * once we have this many bytes we can start with try and work out
  114.  * what we have...
  115.  */
  116. return PACK_HEADER_LEN;
  117. }
  118. size_t CConnectManager::GetMessageSize( 
  119. const OnlineGameLib::Win32::CIOBuffer *pBuffer ) const
  120. {
  121. const BYTE *pData = pBuffer->GetBuffer();
  122. const size_t used = pBuffer->GetUsed();
  123. PACK_HEADER ph = {0};
  124. /*
  125.  * First, verify the flag of a message
  126.  */
  127. if ( used > PACK_HEADER_LEN )
  128. {
  129. memcpy( &ph, pData, PACK_HEADER_LEN );
  130. if ( PACK_BEGIN_FLAG == ph.cPackBeginFlag && 
  131.  PACK_END_FLAG == ph.cPackEndFlag )
  132. {
  133. WORD wCRC = MAKE_CRC_DATE( PACK_BEGIN_FLAG, PACK_END_FLAG, ph.wDataLen );
  134. if ( ph.wCRCData == wCRC )
  135. {
  136. return ph.wDataLen + PACK_HEADER_LEN;
  137. }
  138. }
  139. }
  140. return 0;
  141. }
  142. OnlineGameLib::Win32::CIOBuffer *CConnectManager::ProcessDataStream( 
  143. OnlineGameLib::Win32::CIOBuffer *pBuffer)
  144. {
  145. const size_t used = pBuffer->GetUsed();
  146. if ( used >= GetMinimumMessageSize() )
  147. {
  148. const size_t messageSize = GetMessageSize( pBuffer );
  149. if ( messageSize == 0 )
  150. {
  151. /*
  152.  * havent got a complete message yet.
  153.  * we null terminate our messages in the buffer, so we need to reserve
  154.  * a byte of the buffer for this purpose...
  155.  */
  156. if ( used == ( pBuffer->GetSize() - 1 ) )
  157. {
  158. Output( _T("Too much data!") );
  159. /*
  160.  * Write this message and then shutdown the sending side of the socket.
  161.  */
  162. Output( "found error and close this connection!" );
  163. Shutdown();
  164. /*
  165.  * throw the rubbish away
  166.  */
  167. pBuffer->Empty();
  168. }
  169. }
  170. else if ( used == messageSize )
  171. {
  172. Output( _T("Got a complete message and begin to process it") );
  173. /*
  174.  * we have a whole, distinct, message
  175.  */
  176. ProcessCommand( pBuffer );
  177. pBuffer->Empty();
  178. }
  179. else if (used > messageSize)
  180. {
  181. Output(_T("Got message plus extra data"));
  182. /*
  183.  * we have a message, plus some more data
  184.  * 
  185.  * allocate a new buffer, copy the extra data into it and try again...
  186.  */
  187. OnlineGameLib::Win32::CIOBuffer *pMessage = pBuffer->SplitBuffer( messageSize );
  188. ProcessCommand( pMessage );
  189. pMessage->Release();
  190. }
  191. }
  192. /*
  193.  * Reissue a read into the same buffer to collect more data
  194.  */
  195. return pBuffer;
  196. }
  197. bool ClientStartup( 
  198. JX_CLIENT_
  199. )
  200. {
  201. g_theJXClient.Start();
  202. return true;
  203. }
  204. void ClientCleanup( JX_CLIENT_ )
  205. {
  206. try
  207. {
  208. g_theJXClient.StopConnections();
  209. g_theJXClient.WaitForShutdownToComplete();
  210. }
  211. catch( const CException &e )
  212. {
  213. Output(_T("Exception: ") + e.GetWhere() + _T(" - ") + e.GetMessage());
  214. }
  215. catch(...)
  216. {
  217. Output(_T("Unexpected exception"));
  218. }
  219. }
  220. bool ConnectTo( 
  221. JX_CLIENT_
  222. const OnlineGameLib::Win32::_tstring &addressToConnectServer,
  223. unsigned short portToConnectServer )
  224. {
  225. bool ok = false;
  226. try
  227. {
  228. g_theJXClient.ConnectTo( addressToConnectServer, portToConnectServer );
  229. g_theJXClient.StartConnections();
  230. ok = true;
  231. }
  232. catch( const CException &e )
  233. {
  234. Output(_T("Exception: ") + e.GetWhere() + _T(" - ") + e.GetMessage());
  235. }
  236. catch(...)
  237. {
  238. Output(_T("Unexpected exception"));
  239. }
  240. return ok;
  241. }
  242. void InstallCallBack( JX_CLIENT_ CALLBACK_CLIENT_EVENT pfn )
  243. {
  244. g_theManager.InstallCallBack( pfn );
  245. }
  246. void Client_Start()
  247. {
  248. g_theJXClient.StartConnections();
  249. }
  250. void Client_Pause()
  251. {
  252. g_theJXClient.StopConnections();
  253. }
  254. void Client_Begin()
  255. {
  256. }
  257. void Client_End()
  258. {
  259. }
  260. /*
  261.  * Client usage
  262.  */
  263. inline void RecvFromServer( 
  264. JX_CLIENT_ 
  265. const char *pData, 
  266. size_t dataLength )
  267. {
  268. g_theManager.RecvFromServer( pData, dataLength );
  269. }
  270. inline const char *GetFromServer( size_t &dataLength )
  271. {
  272. return g_theManager.GetFromClient( dataLength );
  273. }
  274.  
  275. inline void SendToServer( 
  276. JX_CLIENT_ 
  277. void *pData, 
  278. size_t dataLength )
  279. {
  280. g_theJXClient.Write( reinterpret_cast<const char*>( pData ), dataLength );
  281. }
  282. void Shutdown( JX_CLIENT_ )
  283. {
  284. //g_theJXClient.InitiateShutdown();
  285. g_theJXClient.StopConnections();
  286. }
  287. void ConnectServer( JX_CLIENT_ )
  288. {
  289. g_theManager.ConnectServer();
  290. }
  291. void DisConnetServer( JX_CLIENT_ )
  292. {
  293. g_theManager.DisConnetServer();
  294. }