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

模拟服务器

开发平台:

C/C++

  1. // Goddess.cpp : Defines the entry point for the application.
  2. //
  3. #include "stdafx.h"
  4. #include "resource.h"
  5. #include <objbase.h>
  6. #include <initguid.h>
  7. #include <winsock2.h>
  8. #include <process.h>
  9. #include "kprotocoldef.h"
  10. #include "IDBRoleServer.h"
  11. #include "console.h"
  12. #include "Event.h"
  13. #include "macro.h"
  14. #include "Inifile.h"
  15. #include "Utils.h"
  16. #include "tstring.h"
  17. #include "Library.h"
  18. #include "Buffer.h"
  19. #include "CriticalSection.h"
  20. #include "IServer.h"
  21. #include "HeavenInterface.h"
  22. #include "ClientNode.h"
  23. #include <iostream>
  24. #include <strstream>
  25. #include <string>
  26. #include <list>
  27. #include "FilterTextLib.h"
  28. #include "RoleNameFilter.h"
  29. using namespace std;
  30. using OnlineGameLib::Win32::Console::clrscr;
  31. using OnlineGameLib::Win32::Console::setcolor;
  32. using OnlineGameLib::Win32::CEvent;
  33. using OnlineGameLib::Win32::CIniFile;
  34. using OnlineGameLib::Win32::GetAppFullPath;
  35. using OnlineGameLib::Win32::_tstring;
  36. using OnlineGameLib::Win32::CLibrary;
  37. using OnlineGameLib::Win32::ToString;
  38. using OnlineGameLib::Win32::CPackager;
  39. using OnlineGameLib::Win32::CBuffer;
  40. using OnlineGameLib::Win32::CCriticalSection;
  41. /*
  42.  * User data
  43.  */
  44. static CLibrary g_theHeavenLibrary( "heaven.dll" );
  45. static CEvent g_hQuitEvent( NULL, true, false );
  46. static CEvent g_hStartWorkEvent( NULL, true, false );
  47. static size_t g_nMaxRoleCount = 3;
  48. static unsigned short g_nServerPort = 5001;
  49. static IServer *g_pServer = NULL;
  50. static HANDLE g_hThread = NULL;
  51. static CCriticalSection g_csPlayer;
  52. typedef map< size_t, CClientNode * > stdPlayerMap;
  53. static  stdPlayerMap g_thePlayer;
  54. static CPackager g_theRecv;
  55. static CPackager g_theSend;
  56. UINT g_nDBEngineLoop = 0;
  57. UINT g_nServiceLoop = 0;
  58. extern HWND hListOutput;
  59. #define WM_CREATE_ENGINE WM_USER + 0x100
  60. #define WM_ADD_CLIENT WM_USER + 0x200
  61. #define WM_DEL_CLIENT WM_USER + 0x300
  62. CFilterTextLib g_libFilterText;
  63. CRoleNameFilter g_fltRoleName;
  64. static size_t g_BackupSleepTime = 1;  //备份线程自动挂起时间
  65. static bool g_IsBackupSuspend = false;  //备份线程是否手工挂起
  66. /*
  67.  * Helper function
  68.  */
  69. BOOL CALLBACK MainWndProc( HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam );
  70. bool CreateDatabaseEngine( HWND hwnd );
  71. void DestroyDatabaseEngine();
  72. void LoadSetting();
  73. void SaveSetting();
  74. //==========监视的线程
  75. DWORD WINAPI MonitorProc(LPVOID lpParameter) {
  76. while(true) {
  77. Sleep(60 * 1000); //1次
  78. }
  79. return 0;
  80. }
  81. /*
  82.  * Callback function
  83.  */
  84. typedef HRESULT ( __stdcall * pfnCreateServerInterface )(
  85. REFIID riid,
  86. void **ppv
  87. );
  88. void __stdcall ServerEventNotify(
  89. LPVOID lpParam,
  90. const unsigned long &ulnID,
  91. const unsigned long &ulnEventType )
  92. {
  93. HWND hwnd = ( HWND )lpParam;
  94. switch( ulnEventType )
  95. {
  96. case enumClientConnectCreate:
  97. {
  98. CClientNode *pNode = CClientNode::AddNode( g_pServer, ulnID );
  99. if ( pNode )
  100. {
  101. CCriticalSection::Owner lock( g_csPlayer );
  102. g_thePlayer.insert( stdPlayerMap::value_type( ulnID, pNode ) );
  103. ::PostMessage( hwnd, WM_ADD_CLIENT, ulnID, 0 );
  104. }
  105. }
  106. break;
  107. case enumClientConnectClose:
  108. {
  109. {
  110. CCriticalSection::Owner lock( g_csPlayer );
  111. stdPlayerMap::iterator it;
  112. if ( g_thePlayer.end() != ( it = g_thePlayer.find( ulnID ) ) )
  113. {
  114. g_thePlayer.erase( ulnID );
  115. ::PostMessage( hwnd, WM_DEL_CLIENT, ulnID, 0 );
  116. }
  117. }
  118. CClientNode::DelNode( ulnID );
  119. }
  120. break;
  121. }
  122. }
  123. DWORD WINAPI ThreadProcess( void *pParam )
  124. {
  125. IServer *pServer = ( IServer * )pParam;
  126. ASSERT( pServer );
  127. g_hStartWorkEvent.Wait();
  128. //try
  129. //{
  130. while ( !g_hQuitEvent.Wait( 0 ) )
  131. {
  132. {
  133. CCriticalSection::Owner lock( g_csPlayer );
  134. stdPlayerMap::iterator it;
  135. for ( it = g_thePlayer.begin(); it != g_thePlayer.end(); it ++ )
  136. {
  137. UINT index = ( *it ).first;
  138. CClientNode *pClientNode = ( *it ).second;
  139. size_t datalength = 0;
  140. const char *pData = ( const char * )pServer->GetPackFromClient( index, datalength );
  141. while ( pClientNode && pData && datalength )
  142. {
  143. pClientNode->AppendData( pData, datalength );
  144. pData = ( const char * )pServer->GetPackFromClient( index, datalength );
  145. }
  146. }
  147. }
  148. if ( ++ g_nServiceLoop & 0x80000000 )
  149. {
  150. g_nServiceLoop = 0;
  151. }
  152. if ( g_nServiceLoop & 0x1 )
  153. {
  154. ::Sleep( 1 );
  155. }
  156. }
  157. //}
  158. //catch(...)
  159. //{
  160. // ::MessageBox( NULL, "ThreadProcess was error!", "Warning", MB_OK );
  161. //}
  162. return 0L;
  163. }
  164. int APIENTRY WinMain(HINSTANCE hInstance,
  165.                      HINSTANCE hPrevInstance,
  166.                      LPSTR     lpCmdLine,
  167.                      int       nCmdShow)
  168. {
  169. //role name filter
  170. if (!g_libFilterText.Initialize()
  171. || !g_fltRoleName.Initialize())
  172. {
  173. MessageBox(NULL, "text filter's initing has failed", "error", MB_OK|MB_ICONERROR);
  174. return -1;
  175. }
  176. HWND hwndMain = ::CreateDialog( hInstance, 
  177. MAKEINTRESOURCE( IDD_DLG_GODDESS ),
  178. NULL, 
  179. (DLGPROC)MainWndProc );
  180. ASSERT( hwndMain );
  181. ::ShowWindow( hwndMain, SW_SHOWNORMAL );
  182. ::UpdateWindow( hwndMain );
  183. hListOutput = ::GetDlgItem( hwndMain, IDC_OUTPUT );//输出list
  184. BOOL bRet;
  185. MSG msg;
  186. while ( ( bRet = ::GetMessage( &msg, NULL, 0, 0 ) ) != 0 )
  187. {
  188. if ( !IsWindow( hwndMain ) || !IsDialogMessage( hwndMain, &msg ) )
  189. {
  190. ::TranslateMessage( &msg );
  191. ::DispatchMessage( &msg );
  192. }
  193. }
  194. //rolename filter
  195. g_fltRoleName.Uninitialize();
  196. g_libFilterText.Uninitialize();
  197. return msg.wParam;
  198. }
  199. /*
  200.  *
  201.  * MainWndProc() - Main window callback procedure.
  202.  *  
  203.  */
  204. BOOL CALLBACK MainWndProc( HWND hwnd, 
  205.                        UINT msg,
  206.                        WPARAM wParam,
  207.                        LPARAM lParam )
  208. {
  209. static const UINT g_nIDEvent = 0x100;
  210. static const UINT g_nElapse = 500;
  211. static const char g_szBaseInfo[] = "....................";
  212. static const int g_nDots = sizeof( g_szBaseInfo ) - 1;
  213. static UINT g_nLastServiceLoop = g_nServiceLoop;
  214. static int g_nServiceStep = g_nDots;
  215. static UINT g_nLastDBEngineLoop= g_nDBEngineLoop;
  216. static int g_nDBEngineStep = g_nDots;
  217. BOOL bTranslated = TRUE;
  218. switch ( msg )
  219. {
  220. case WM_TIMER:
  221. {
  222. if ( g_nLastServiceLoop != g_nServiceLoop )
  223. {
  224. g_nServiceStep = ( -- g_nServiceStep > 0 ) ? g_nServiceStep : g_nDots;
  225. ::SetDlgItemText( hwnd, IDC_STATIC_SERVICE, ( const char * )g_szBaseInfo + g_nServiceStep );
  226. g_nLastServiceLoop = g_nServiceLoop;
  227. }
  228. if ( g_nLastDBEngineLoop != g_nDBEngineLoop )
  229. {
  230. g_nDBEngineStep = ( -- g_nDBEngineStep > 0 ) ? g_nDBEngineStep : g_nDots;
  231. ::SetDlgItemText( hwnd, IDC_STATIC_DATABASE, ( const char * )g_szBaseInfo + g_nDBEngineStep );
  232. g_nLastDBEngineLoop = g_nDBEngineLoop;
  233. }
  234. if(IsBackupThreadWorking())
  235. {
  236. ::EnableWindow( GetDlgItem( hwnd, IDC_BTN_BACKUP_SUS_RES ), TRUE );
  237. ::SetWindowText(GetDlgItem( hwnd, IDC_LAB_BACKUP_STATUS ),
  238. "Backup thread status: Sleeping");
  239. ::EnableWindow( GetDlgItem( hwnd, IDC_BTN_BACKUP_MANUAL ), TRUE );
  240. if(IsBackupWorking())
  241. {
  242. ::EnableWindow( GetDlgItem( hwnd, IDC_BTN_BACKUP_SUS_RES ), FALSE );
  243. ::SetWindowText(GetDlgItem( hwnd, IDC_LAB_BACKUP_STATUS ),
  244. "Backup thread status: Running");
  245. ::EnableWindow( GetDlgItem( hwnd, IDC_BTN_BACKUP_MANUAL ), FALSE );
  246. }
  247. else if (g_IsBackupSuspend)
  248. {
  249. ::EnableWindow( GetDlgItem( hwnd, IDC_BTN_BACKUP_SUS_RES ), TRUE );
  250. ::SetWindowText(GetDlgItem( hwnd, IDC_LAB_BACKUP_STATUS ),
  251. "Backup thread status: Suspended");
  252. ::EnableWindow( GetDlgItem( hwnd, IDC_BTN_BACKUP_MANUAL ), TRUE );
  253. }
  254. }
  255. else
  256. {
  257. ::EnableWindow( GetDlgItem( hwnd, IDC_BTN_BACKUP_SUS_RES ), FALSE );
  258. ::SetWindowText(GetDlgItem( hwnd, IDC_LAB_BACKUP_STATUS ),
  259. "Backup thread status: Stop");
  260. ::EnableWindow( GetDlgItem( hwnd, IDC_BTN_BACKUP_MANUAL ), FALSE );
  261. }
  262. }
  263. break;
  264. case WM_INITDIALOG:
  265. LoadSetting();
  266. ::SetDlgItemInt( hwnd, IDC_EDIT_PORT, g_nServerPort, FALSE );
  267. ::SetDlgItemInt( hwnd, IDC_EDIT_MAXNUM_ROLE, g_nMaxRoleCount, FALSE );
  268. ::SetDlgItemInt( hwnd, IDC_EDIT_BACKUP_SLEEP_TIME, g_BackupSleepTime, FALSE );
  269. ::SetTimer( hwnd, g_nIDEvent, g_nElapse, NULL );
  270. return TRUE;
  271. break;
  272. case WM_CLOSE:
  273. {
  274. if ( IDYES == ::MessageBox( hwnd, "Are you sure quit?", "Info", MB_YESNO | MB_ICONQUESTION ) )
  275. {
  276. DestroyDatabaseEngine();
  277. ::KillTimer( hwnd, g_nIDEvent );
  278. g_nServerPort = ::GetDlgItemInt( hwnd, IDC_EDIT_PORT, &bTranslated, FALSE );
  279. g_nMaxRoleCount = ::GetDlgItemInt( hwnd, IDC_EDIT_MAXNUM_ROLE, &bTranslated, FALSE );
  280. g_BackupSleepTime = ::GetDlgItemInt( hwnd, IDC_EDIT_BACKUP_SLEEP_TIME, &bTranslated, FALSE );
  281. SaveSetting();
  282. ::DestroyWindow( hwnd );
  283. ::PostQuitMessage( 0 );
  284. }
  285. }
  286. return TRUE;
  287. break;
  288. case WM_COMMAND:
  289. switch ( wParam )
  290. {
  291. case IDOK:
  292. ::EnableWindow( GetDlgItem( hwnd, IDOK ), FALSE );
  293. ::EnableWindow( GetDlgItem( hwnd, IDC_EDIT_PORT ), FALSE );
  294. ::EnableWindow( GetDlgItem( hwnd, IDC_EDIT_MAXNUM_ROLE ), FALSE );
  295. ::EnableWindow( GetDlgItem( hwnd, IDC_EDIT_BACKUP_SLEEP_TIME ), FALSE );
  296. ::SetWindowText( hwnd, "Goddess - [Start up...]" );
  297. ::PostMessage( hwnd, WM_CREATE_ENGINE, 0L, 0L );
  298. break;
  299. case IDCANCEL:
  300. ::PostMessage( hwnd, WM_CLOSE, 0L, 0L );
  301. break;
  302. case IDC_BTN_BACKUP_MANUAL:
  303. if(!IsBackupThreadWorking())
  304. MessageBox(hwnd, "Backup thread is not started yet.",
  305. "Information",MB_OK | MB_ICONEXCLAMATION);
  306. if(!DoManualBackup())
  307. MessageBox(hwnd, "Unable to start manual backup.nPlease try later.",
  308. "Information",MB_OK | MB_ICONEXCLAMATION);
  309. break;
  310. case IDC_RESTART:
  311. CClientNode::End();
  312. ReleaseDBInterface();
  313. InitDBInterface(g_nMaxRoleCount);
  314. CClientNode::Start( g_pServer );
  315. break;
  316. case IDC_BTN_BACKUP_SUS_RES:
  317. if(!IsBackupThreadWorking())
  318. MessageBox(hwnd, "Backup thread is not started yet.",
  319. "Information",MB_OK | MB_ICONEXCLAMATION);
  320. else if(g_IsBackupSuspend)
  321. {
  322. if(ResumeBackupTimer())
  323. {
  324. g_IsBackupSuspend = false;
  325. ::SetWindowText(GetDlgItem( hwnd, IDC_BTN_BACKUP_SUS_RES ),
  326. "Suspend");
  327. }
  328. else
  329. MessageBox(hwnd, "Unable to resume backup thread.nPlease try later.",
  330. "Information",MB_OK | MB_ICONEXCLAMATION);
  331. }
  332. else
  333. {
  334. if(SuspendBackupTimer())
  335. {
  336. g_IsBackupSuspend = true;
  337. ::SetWindowText(GetDlgItem( hwnd, IDC_BTN_BACKUP_SUS_RES ),
  338. "Resume");
  339. }
  340. else
  341. MessageBox(hwnd, "Unable to suspend backup thread.nPlease try later.",
  342. "Information",MB_OK | MB_ICONEXCLAMATION);
  343. }
  344. break;
  345. }
  346. break;
  347. case WM_CREATE_ENGINE:
  348. {
  349. g_nServerPort = ::GetDlgItemInt( hwnd, IDC_EDIT_PORT, &bTranslated, FALSE );
  350. g_nMaxRoleCount = ::GetDlgItemInt( hwnd, IDC_EDIT_MAXNUM_ROLE, &bTranslated, FALSE );
  351. g_BackupSleepTime = ::GetDlgItemInt( hwnd, IDC_EDIT_BACKUP_SLEEP_TIME, &bTranslated, FALSE );
  352. CreateDatabaseEngine( hwnd );
  353. /* DWORD dwThreadId, dwThrdParam = 1;
  354. HANDLE hMonitorThread = CreateThread(
  355. NULL, // no security attributes 
  356. 0, // use default stack size  
  357. MonitorProc, // thread function 
  358. &dwThrdParam, // argument to thread function 
  359. 0, // use default creation flags 
  360. &dwThreadId); // returns the thread identifier 
  361. */
  362. ::SetWindowText( hwnd, "Goddess - [Enable]" );
  363. }
  364. break;
  365. case WM_ADD_CLIENT:
  366. {
  367. const char *pText = g_pServer->GetClientInfo( wParam );
  368. if ( pText && pText[0] )
  369. {
  370. HWND hCtrl = ::GetDlgItem( hwnd, IDC_LIST_CLIENT );
  371. if ( hCtrl && ::IsWindow( hCtrl ) )
  372. {
  373. int nIndex = ::SendMessage( hCtrl, LB_ADDSTRING, 0, ( LPARAM )pText );
  374. if ( LB_ERR != nIndex )
  375. {
  376. ::SendMessage( hCtrl, LB_SETITEMDATA, nIndex, wParam );
  377. }
  378. }
  379. }
  380. }
  381. break;
  382. case WM_DEL_CLIENT:
  383. {
  384. HWND hCtrl = ::GetDlgItem( hwnd, IDC_LIST_CLIENT );
  385. if ( hCtrl && ::IsWindow( hCtrl ) )
  386. {
  387. int nCount = ::SendMessage( hCtrl, LB_GETCOUNT, 0, 0 );
  388. for ( int i=0; i<nCount, LB_ERR != nCount; i++ )
  389. {
  390. UINT nSearchID = 0;
  391. if ( wParam == ( nSearchID = ::SendMessage( hCtrl, LB_GETITEMDATA, i, 0 ) ) )
  392. {
  393. ::SendMessage( hCtrl, LB_DELETESTRING, i, 0 );
  394. return TRUE;
  395. }
  396. }
  397. }
  398. }
  399. break;
  400. default:
  401. break;
  402. }
  403. /*
  404.  * Clean up any unused messages by calling DefWindowProc
  405.  */
  406. return FALSE;
  407. }
  408. bool CreateDatabaseEngine( HWND hwnd )
  409. {
  410. if ( !InitDBInterface( g_nMaxRoleCount ) )
  411. {
  412. ::MessageBox( NULL, "Setup dbserver is failed!", "Warning", MB_OK | MB_ICONSTOP );
  413. return false;
  414. }
  415. StartBackupTimer(g_BackupSleepTime); //开始运行备份线程
  416. ::SetWindowText(GetDlgItem( hwnd, IDC_LAB_BACKUP_STATUS ),
  417. "Backup thread status: Running");
  418. /*
  419.  * Open this server to client
  420.  */
  421. pfnCreateServerInterface pFactroyFun = ( pfnCreateServerInterface )( g_theHeavenLibrary.GetProcAddress( "CreateInterface" ) );
  422. IServerFactory *pServerFactory = NULL;
  423. if ( pFactroyFun && SUCCEEDED( pFactroyFun( IID_IServerFactory, reinterpret_cast< void ** >( &pServerFactory ) ) ) )
  424. {
  425. pServerFactory->SetEnvironment( 10, 10, 20, 4 * 1024 * 1024 );
  426. pServerFactory->CreateServerInterface( IID_IIOCPServer, reinterpret_cast< void ** >( &g_pServer ) );
  427. pServerFactory->Release();
  428. }
  429. if ( !g_pServer )
  430. {
  431. ::MessageBox( NULL, "Initialization failed! Don't find a correct heaven.dll", "Warning", MB_OK | MB_ICONSTOP );
  432. return false;
  433. }
  434. g_pServer->Startup();
  435. g_pServer->RegisterMsgFilter( ( void * )hwnd, ServerEventNotify );
  436. if ( FAILED( g_pServer->OpenService( INADDR_ANY, g_nServerPort ) ) )
  437. {
  438. return false;
  439. }
  440. DWORD dwThreadID = 0L;
  441. IServer *pCloneServer = NULL;
  442. g_pServer->QueryInterface( IID_IIOCPServer, ( void ** )&pCloneServer );
  443. g_hThread = ::CreateThread( NULL, 0, ThreadProcess, ( void * )pCloneServer, 0, &dwThreadID );
  444. if ( !g_hThread )
  445. {
  446. return false;
  447. }
  448. CClientNode::Start( g_pServer );
  449. g_hStartWorkEvent.Set();
  450. return true;
  451. }
  452. void DestroyDatabaseEngine()
  453. {
  454. CClientNode::End();
  455. g_hQuitEvent.Set();
  456. DWORD result = ::WaitForSingleObject( g_hThread, 50000 );
  457. if ( result == WAIT_TIMEOUT )
  458. {
  459. ::TerminateThread( g_hThread, ( DWORD )( -1 ) );
  460. }
  461. SAFE_CLOSEHANDLE( g_hThread );
  462. if ( g_pServer )
  463. {
  464. g_pServer->CloseService();
  465. g_pServer = NULL;
  466. }
  467. SAFE_RELEASE( g_pServer );
  468. ReleaseDBInterface();
  469. }
  470. void LoadSetting()
  471. {
  472. CIniFile theConfigFile;
  473. _tstring sAppPath = GetAppFullPath( NULL );
  474. _tstring sConfigFile;
  475. sConfigFile = sAppPath + "Goddess.cfg";
  476. theConfigFile.SetFile( sConfigFile.c_str() );
  477. g_nServerPort = theConfigFile.ReadInteger( "Setting", "Port", 5001 );
  478. g_nMaxRoleCount = theConfigFile.ReadInteger( "Setting", "MaxRoleCount", 3 );
  479. g_BackupSleepTime = theConfigFile.ReadInteger( "Setting", "BackupSleepTime", 3 );
  480. }
  481. void SaveSetting()
  482. {
  483. CIniFile theConfigFile;
  484. _tstring sAppPath = GetAppFullPath( NULL );
  485. _tstring sConfigFile;
  486. sConfigFile = sAppPath + "Goddess.cfg";
  487. theConfigFile.SetFile( sConfigFile.c_str() );
  488. theConfigFile.WriteInteger( "Setting", "Port", g_nServerPort );
  489. theConfigFile.WriteInteger(  "Setting", "MaxRoleCount", g_nMaxRoleCount );
  490. theConfigFile.WriteInteger(  "Setting", "BackupSleepTime", g_BackupSleepTime );
  491. }