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

模拟服务器

开发平台:

C/C++

  1. #include "stdafx.h"
  2. #include "SmartClient.h"
  3. #include "Macro.h"
  4. #include "KProtocolDef.h"
  5. #include "AccountLoginDef.h"
  6. #include "Buffer.h"
  7. #include "msg_define.h"
  8. #include "Macro.h"
  9. #include "../Engine/Src/KWin32.h"
  10. #include "../Engine/Src/KSG_MD5_String.h"
  11. #include "inoutmac.h"
  12. using OnlineGameLib::Win32::CPackager;
  13. using OnlineGameLib::Win32::CCriticalSection;
  14. using OnlineGameLib::Win32::CBuffer;
  15. OnlineGameLib::Win32::CLibrary CSmartClient::m_theRainbowLib( "rainbow.dll" );
  16. static const DWORD g_dwServerIdentify = 0xAEFC07B5;
  17. CSmartClient g_theSmartClient;
  18. CSmartClient::CSmartClient()
  19. : m_hWorkingThread( NULL )
  20. , m_pClient( NULL )
  21. , m_hwndContain( NULL )
  22. , m_nSvrPort( 0 )
  23. , m_theAllocator( 1024, 500 )
  24. {
  25. }
  26. CSmartClient::~CSmartClient()
  27. {
  28. if ( m_pClient )
  29. {
  30. m_pClient->Cleanup();
  31. }
  32. SAFE_RELEASE( m_pClient );
  33. }
  34. bool CSmartClient::Open( const char * const pAddressToConnectServer, 
  35. unsigned short usPortToConnectServer, 
  36. HWND hwndContain,
  37. const char *pName,
  38. const char *pPwd,
  39. bool bReLink /* true */ )
  40. {
  41. if ( !pName || !pPwd )
  42. {
  43. return false;
  44. }
  45. m_sUserName = pName;
  46. m_sUserPwd = pPwd;
  47. m_sSvrIP = pAddressToConnectServer;
  48. m_nSvrPort = usPortToConnectServer;
  49. m_hwndContain = hwndContain;
  50. /*
  51.  * m_bReLink == true ( default )
  52.  */
  53. m_bReLink = bReLink;
  54. m_ClientStatus = enumClientConnect;
  55. IClient* pClient = _Connect();
  56. if (pClient)
  57. {
  58. _Verify(pClient, false);
  59. SAFE_RELEASE(pClient);
  60. }
  61. bool ok = CreateConnectThread();
  62. return ok;
  63. }
  64. void CSmartClient::Close()
  65. {
  66. SetClientStatus(enumClientError); //停止线程
  67. }
  68. void __stdcall CSmartClient::EventNotify( LPVOID lpParam, 
  69. const unsigned long &ulnEventType )
  70. {
  71. CSmartClient *pThis = reinterpret_cast< CSmartClient * >( lpParam );
  72. ASSERT( pThis );
  73. try
  74. {
  75. pThis->_EventNotify( ulnEventType );
  76. }
  77. catch(...)
  78. {
  79. TRACE( "CSmartClient::EventNotify exception!" );
  80. }
  81. }
  82. void CSmartClient::_EventNotify( const unsigned long &ulnEventType )
  83. {
  84. switch( ulnEventType )
  85. {
  86. case enumServerConnectCreate:
  87. ::PostMessage( m_hwndContain, WM_SERVER_STATUS, ACCOUNTSERVER_NOTIFY, CONNECTED );
  88. break;
  89. case enumServerConnectClose:
  90. {
  91. ::PostMessage( m_hwndContain, WM_SERVER_STATUS, ACCOUNTSERVER_NOTIFY, DICONNECTED );
  92. SwitchToConnecting();
  93. }
  94. break;
  95. }
  96. }
  97. bool CSmartClient::CreateConnectThread()
  98. {
  99. /*
  100.  * Start a working thread
  101.  */
  102. DWORD dwThreadID = 0;
  103. m_hWorkingThread = ::CreateThread( NULL, 
  104. 0, 
  105. WorkingThreadFunction, 
  106. ( void * )this, 
  107. 0, 
  108. &dwThreadID );
  109. if ( m_hWorkingThread == INVALID_HANDLE_VALUE )
  110. {
  111. return false;
  112. }
  113. return true;
  114. }
  115. DWORD WINAPI CSmartClient::WorkingThreadFunction( void *pV )
  116. {
  117. CSmartClient *pThis = reinterpret_cast< CSmartClient * >( pV );
  118. ASSERT( pThis );
  119. IClient* pClient = NULL;
  120. try
  121. {
  122. while (!pThis->IsError())
  123. {
  124. if (pThis->IsConnecting())
  125. {
  126. if (pThis->m_pClient)
  127. {
  128. pThis->m_pClient->Cleanup();
  129. pThis->m_pClient = NULL;
  130. }
  131. SAFE_RELEASE( pClient );
  132. pClient = pThis->_Connect();
  133. }
  134. else if (pThis->IsVerifying())
  135. {
  136. pThis->_Verify(pClient, true);
  137. SAFE_RELEASE( pClient );
  138. }
  139. Sleep(10);
  140. }
  141. }
  142. catch(...)
  143. {
  144. ::MessageBox( NULL, "Run a working thread is failed!", "CSmartClient class", MB_OK );
  145. }
  146. ::PostMessage(pThis->m_hwndContain, WM_CLOSE, NULL, NULL);
  147. return 0;
  148. }
  149. IClient* CSmartClient::_Connect()
  150. {
  151. if ( !IsConnecting() )
  152. return NULL;
  153. #ifdef CONSOLE_DEBUG
  154. cprintf( "Begin connectn");
  155. #endif
  156. IClient *pClient = NULL;
  157. /*
  158.  * There is connectted the heaven by the rainbow
  159.  */
  160. pfnCreateClientInterface pClientFactroyFun = ( pfnCreateClientInterface )( m_theRainbowLib.GetProcAddress( _T( "CreateInterface" ) ) );
  161. IClientFactory *pClientFactory = NULL;
  162. if ( pClientFactroyFun && SUCCEEDED( pClientFactroyFun( IID_IClientFactory, reinterpret_cast< void ** >( &pClientFactory ) ) ) )
  163. {
  164. pClientFactory->SetEnvironment( 1024 * 1024 );
  165. pClientFactory->CreateClientInterface( IID_IESClient, reinterpret_cast< void ** >( &pClient ) );
  166. SAFE_RELEASE( pClientFactory );
  167. }
  168. if ( pClient )
  169. {
  170. pClient->Startup();
  171. pClient->RegisterMsgFilter( reinterpret_cast< void * >( this ), EventNotify );
  172. if ( FAILED( pClient->ConnectTo( m_sSvrIP.c_str(), m_nSvrPort ) ) )
  173. {
  174. pClient->Cleanup();
  175. SAFE_RELEASE( pClient );
  176. #ifdef CONSOLE_DEBUG
  177. cprintf( "Reconnect Failedn");
  178. #endif
  179. ::Sleep( 5000 );
  180. return NULL;
  181. }
  182. else
  183. {
  184. SetClientStatus(enumClientVerify);
  185. }
  186. }
  187. return pClient;
  188. }
  189. void CSmartClient::_Verify(IClient* pClient, bool bDisconnect)
  190. {
  191. if (!IsVerifying())
  192. return;
  193. if (pClient == NULL)
  194. return;
  195. #ifdef CONSOLE_DEBUG
  196. cprintf( "Begin verifyn");
  197. #endif
  198. /*
  199. * Send a login command
  200. */
  201. const size_t datalength = sizeof( KServerAccountUserLoginInfo ) + 1;
  202. BYTE *pData = new BYTE[datalength];
  203. KServerAccountUserLoginInfo serlogin;
  204. serlogin.Size = sizeof( KServerAccountUserLoginInfo );
  205. serlogin.Type = ServerAccountUserLoginInfo;
  206. serlogin.Version = ACCOUNT_CURRENT_VERSION;
  207. serlogin.Operate = g_dwServerIdentify;
  208. size_t lenTag, lenScr;
  209. lenTag = sizeof( serlogin.Account );
  210. lenScr = m_sUserName.size() + 1;
  211. lenTag = ( lenTag > lenScr ) ? lenScr : lenTag;
  212. memcpy( serlogin.Account, m_sUserName.c_str(), lenTag );
  213. serlogin.Account[lenTag - 1] = '';
  214. lenTag = sizeof( serlogin.Password );
  215. KSG_StringToMD5String(serlogin.Password, m_sUserPwd.c_str() /*szPassword*/);
  216. serlogin.Address = -1;
  217. // add by spe 2003/08/08
  218. gGetMacAndIPAddress(NULL, NULL, serlogin.MacAddress, &serlogin.Address);
  219. if ( bDisconnect )
  220. {
  221. *pData = c2s_gatewayverifyagain;
  222. }
  223. else
  224. {
  225. *pData = c2s_gatewayverify;
  226. }
  227. memcpy( pData + 1, &serlogin, sizeof( KServerAccountUserLoginInfo ) );
  228. pClient->SendPackToServer( ( const void * )pData, datalength );
  229. SAFE_DELETE_ARRAY( pData );
  230. /*
  231. * Wait for write back
  232. */
  233. while ( pClient )
  234. {
  235. if ( !IsVerifying() )
  236. {
  237. break; //因为正常的状态变化引起的退出
  238. }
  239. #ifdef CONSOLE_DEBUG
  240. cprintf( "Wait for verifyn");
  241. #endif
  242. size_t nLen = 0;
  243. const void *pData = pClient->GetPackFromServer( nLen );
  244. if ( !pData || 0 == nLen )
  245. {
  246. ::Sleep( 1 );
  247. continue;
  248. }
  249. BYTE cProtocol = CPackager::Peek( pData );
  250. switch ( cProtocol )
  251. {
  252. case s2c_gatewayverify:
  253. {
  254. KAccountUserReturn* pReturn = ( KAccountUserReturn * )( ( ( char * )pData ) + 1 );
  255. nLen--;
  256. if ( pReturn &&
  257. ( g_dwServerIdentify == pReturn->Operate ) && 
  258. ( nLen == sizeof( KAccountUserReturn ) ) )
  259. {
  260. if ( ACTION_SUCCESS == pReturn->nReturn )
  261. {
  262. ::PostMessage( m_hwndContain, WM_SERVER_LOGIN_SUCCESSFUL, 0L, 0L );
  263. pClient->QueryInterface( IID_IESClient, reinterpret_cast< void ** >( &m_pClient ) );
  264. if (SetClientStatus(enumClientNormal))
  265. {
  266. Send(NULL, 0);
  267. #ifdef CONSOLE_DEBUG
  268. cprintf( "Succeed verifyn");
  269. #endif
  270. }
  271. }
  272. else if ( E_ACCOUNT_OR_PASSWORD == pReturn->nReturn )
  273. {
  274. ::PostMessage( m_hwndContain, WM_SERVER_LOGIN_FAILED, enumUsrNamePswdErr, 0L );
  275. SetClientStatus(enumClientError);
  276. }
  277. else if ( E_ADDRESS_OR_PORT == pReturn->nReturn )
  278. {
  279. ::PostMessage( m_hwndContain, WM_SERVER_LOGIN_FAILED, enumIPPortErr, 0L );
  280. SetClientStatus(enumClientError);
  281. }
  282. else
  283. {
  284. ::PostMessage( m_hwndContain, WM_SERVER_LOGIN_FAILED, enumException, 0L );
  285. SetClientStatus(enumClientError);
  286. }
  287. }
  288. }
  289. break;
  290. default:
  291. ASSERT( FALSE );
  292. SetClientStatus(enumClientError);
  293. break;
  294. }
  295. }
  296. }
  297. bool CSmartClient::Send( const void * const pData, const size_t &datalength )
  298. {
  299. if (IsNormal())
  300. {
  301. if (m_pClient)
  302. {
  303. /*
  304.  * Send the histroy information to server
  305.  */
  306. {
  307. CCriticalSection::Owner locker( m_csHistroyList );
  308. stdList::iterator it;
  309. for ( it = m_theHistroyList.begin();
  310. it != m_theHistroyList.end();
  311. it ++ )
  312. {
  313. CBuffer *pBuffer = *it;
  314. if ( pBuffer )
  315. {
  316. m_pClient->SendPackToServer( 
  317. ( const void * )( pBuffer->GetBuffer() ), 
  318. pBuffer->GetUsed() );
  319. SAFE_RELEASE( pBuffer );
  320. }
  321. }
  322. m_theHistroyList.clear();
  323. }
  324. if (pData && datalength)
  325. m_pClient->SendPackToServer( pData, datalength );
  326. return true;
  327. }
  328. }
  329. else if (pData && datalength > 0)
  330. {
  331. /* Store data into buffer */
  332. CCriticalSection::Owner locker( m_csHistroyList );
  333. CBuffer *pBuffer = m_theAllocator.Allocate();
  334. ASSERT( pBuffer );
  335. pBuffer->AddData((BYTE*) pData, datalength );
  336. m_theHistroyList.push_back( pBuffer );
  337. }
  338. return false;
  339. }
  340. const void * CSmartClient::Recv( size_t &datalength )
  341. {
  342. if (IsNormal())
  343. {
  344. if ( m_pClient )
  345. {
  346. return m_pClient->GetPackFromServer( datalength );
  347. }
  348. }
  349. datalength = 0;
  350. return NULL;
  351. }
  352. bool CSmartClient::IsNormal()
  353. {
  354. CCriticalSection::Owner locker(m_csStatus);
  355. return (m_ClientStatus == enumClientNormal);
  356. }
  357. bool CSmartClient::IsConnecting()
  358. {
  359. CCriticalSection::Owner locker(m_csStatus);
  360. return (m_ClientStatus == enumClientConnect);
  361. }
  362. bool CSmartClient::IsVerifying()
  363. {
  364. CCriticalSection::Owner locker(m_csStatus);
  365. return (m_ClientStatus == enumClientVerify);
  366. }
  367. bool CSmartClient::IsError()
  368. {
  369. CCriticalSection::Owner locker(m_csStatus);
  370. return (m_ClientStatus == enumClientError);
  371. }
  372. void CSmartClient::SwitchToConnecting() //切换状态到重连,如有必要会停止重连线程
  373. {
  374. if (m_bReLink)
  375. SetClientStatus(enumClientConnect);
  376. else
  377. SetClientStatus(enumClientError); ; //停止线程
  378. }
  379. bool CSmartClient::SetClientStatus(enumClientStatus nNewS)
  380. {
  381. CCriticalSection::Owner locker(m_csStatus);
  382. if ( nNewS == enumClientError )
  383. {
  384. m_ClientStatus = nNewS;
  385. return true;
  386. }
  387. if (m_ClientStatus == enumClientNormal && nNewS == enumClientConnect)
  388. {
  389. m_ClientStatus = nNewS;
  390. return true;
  391. }
  392. if (m_ClientStatus == enumClientConnect &&
  393. (nNewS == enumClientConnect || nNewS == enumClientVerify)
  394. )
  395. {
  396. m_ClientStatus = nNewS;
  397. return true;
  398. }
  399. if (m_ClientStatus == enumClientVerify &&
  400. (nNewS == enumClientConnect || nNewS == enumClientNormal)
  401. )
  402. {
  403. m_ClientStatus = nNewS;
  404. return true;
  405. }
  406. return false;
  407. }