骑士私服-源码研究笔记

骑士私服-源码研究笔记

学习教程tuzi2014-10-11 8:52:22A+A-

骑士online源代码[端游源码]是用vc6.0编写的,采用c++/c语言。

使用了完成端口这样通讯方式,并且使用共享内存的交互方式

当然还涉及到sql2000的数据库操作。 

开始分析 

1.添加Aujard.ini文件及内容

根据网络上下载的要么没有这个文件要么不全,我补充了一下

[ODBC]

ACCOUNT_DSN=KN_online

ACCOUNT_UID=knight

ACCOUNT_PWD=knight

GAME_DSN=KN_online

GAME_UID=knight

GAME_PWD=knight

LOG_DSN=KN_online

LOG_UID=knight

LOG_PWD=knight

[ZONE_INFO]

GROUP_INFO=1

ZONE_INFO=1 

2.程序分析

程序的入口是:BOOL CAujardDlg::OnInitDialog()函数,也就是我们主界面的初始化函数,这个函数是创建MFC Dialog界面的时候自 带的,但是主要的功能都在这里做了,所以服务端程序Aujard.exe只需要运行就可以不需要做其他操作就能工作。

下面我们一步一步分析OnInitDialog()函数里面的功能。

//------------------------------------------------------------------

// Logfile initialize 主要是记录运行日志

//-----------------------------------------------------------------

CTime time=CTime::GetCurrentTime();

char strLogFile[50];  memset(strLogFile, 0x00, 50);

wsprintf(strLogFile, "AujardLog-%d-%d-%d.txt", time.GetYear(), time.GetMonth(), time.GetDay());

m_LogFile.Open( strLogFile, CFile::modeWrite | CFile::modeCreate | CFile::modeNoTruncate | CFile::shareDenyNone );

m_LogFile.SeekToEnd();

m_iLogFileDay = time.GetDay();

 

//------------------------------------------------------------------

// 创建共享内存 需要三块共享内存

// KNIGHT_DB 保存在内存中的玩家数据最大用户3000人,每个用户4000BYTE

// KNIGHT_SEND

// KNIGHT_RECV

// 由于骑士服务端把用户以及物品等相关信息都是保存在内存中的,为了其他游戏的运

// 行速度采取的办法。(至于什么是共享内存,自己去学习吧,这里不作解释。),然

// 后每10秒钟将内存中的玩家信息保存到数据库中,更新数据库。

//-----------------------------------------------------------------

m_LoggerRecvQueue.InitailizeMMF( MAX_PKTSIZE, MAX_COUNT, SMQ_LOGGERSEND, FALSE ); // 分配 Send Queue 虚拟内存共享方式

m_LoggerSendQueue.InitailizeMMF( MAX_PKTSIZE, MAX_COUNT, SMQ_LOGGERRECV, FALSE ); // 分配 Read Queue 虚拟内存共享方式

//初始化用户KNIGHT_DB共享内存

if( !InitializeMMF() ) {

AfxMessageBox("Main Shared Memory Initialize Fail");

  AfxPostQuitMessage(0);

  return FALSE;

}

 

//------------------------------------------------------------------

// 读取配置文件Aujard.ini 并初始化数据库,连接数据库,使用CDBAgent类

//------------------------------------------------------------------

CString inipath;

inipath.Format( "%s\\Aujard.ini", GetProgPath() );

GetPrivateProfileString( "ODBC", "ACCOUNT_DSN", "", m_strAccountDSN, 24, inipath );

GetPrivateProfileString( "ODBC", "ACCOUNT_UID", "", m_strAccountUID, 24, inipath );

GetPrivateProfileString( "ODBC", "ACCOUNT_PWD", "", m_strAccountPWD, 24, inipath );

GetPrivateProfileString( "ODBC", "GAME_DSN", "", m_strGameDSN, 24, inipath );

GetPrivateProfileString( "ODBC", "GAME_UID", "", m_strGameUID, 24, inipath );

GetPrivateProfileString( "ODBC", "GAME_PWD", "", m_strGamePWD, 24, inipath );

GetPrivateProfileString( "ODBC", "LOG_DSN", "", m_strLogDSN, 24, inipath );

GetPrivateProfileString( "ODBC", "LOG_UID", "", m_strLogUID, 24, inipath );

GetPrivateProfileString( "ODBC", "LOG_PWD", "", m_strLogPWD, 24, inipath );

m_nServerNo = GetPrivateProfileInt("ZONE_INFO", "GROUP_INFO", 1, inipath);

m_nZoneNo = GetPrivateProfileInt("ZONE_INFO", "ZONE_INFO", 1, inipath);

//连接数据库使用CDBAgent类

if( !m_DBAgent.DatabaseInit() ) {

  AfxPostQuitMessage(0);

  return FALSE;

}

 

//------------------------------------------------------------------

// 前提:连接上数据库后

// 从数据库中加载ItemTable表保存在m_ItemtableArray队列中

//------------------------------------------------------------------

if( !LoadItemTable() ) {

  AfxMessageBox("Load ItemTable Fail!!");

  AfxPostQuitMessage(0);

  return FALSE;

 }

 

//------------------------------------------------------------------

// 创建定时器

// 三种不同时间的定时器

//------------------------------------------------------------------

SetTimer( PROCESS_CHECK, 40000, NULL );

SetTimer( CONCURRENT_CHECK, 300000, NULL );

SetTimer( PACKET_CHECK, 120000, NULL);

//定时器函数

void CAujardDlg::OnTimer(UINT nIDEvent)

{

 HANDLE hProcess = NULL;

 switch( nIDEvent ) {

 case PROCESS_CHECK:     

  hProcess = OpenProcess( PROCESS_ALL_ACCESS | PROCESS_VM_READ, FALSE, m_LoggerSendQueue.GetProcessId() );

  if( hProcess == NULL )

   AllSaveRoutine(); // 如果SendQueue队列执行县城推出了,就保存现在内存中的数据

  break;

 case CONCURRENT_CHECK:

  break;

 case SERIAL_TIME:

  g_increase_serial = 50001;

  break;

 case PACKET_CHECK:

  WritePacketLog();

  break;

 }

 

 CDialog::OnTimer(nIDEvent);

}

 

 

//------------------------------------------------------------------

//这个函数的主要功能:时刻读取共享内存中的数据(应该是从E文件共享内存中获取

// 来的,他们两个程序共享内存,E文件时主要的通讯文件,接受到客户端的消息后更

// 新内存,而Augard.exe就是直接读取内存,更新数据库),看一下线程函数

// ReadQueueThrea就能明白了

//

//------------------------------------------------------------------

DWORD id;

 m_hReadQueueThread = ::CreateThread( NULL, 0, ReadQueueThread, (LPVOID)this, 0, &id);

 

// ReadQueueThread线程函数

// 这里记录用户登录、删除用户、选择用户。。。

while(TRUE) {

  if( pMain->m_LoggerRecvQueue.GetFrontMode() != R ) {

   index = 0;

   recvlen = pMain->m_LoggerRecvQueue.GetData( recv_buff );

   if( recvlen > MAX_PKTSIZE ) {

    Sleep(1);

    continue;

   }

   command = GetByte( recv_buff, index );

   switch( command ) {

   case WIZ_LOGIN:

    pMain->AccountLogIn( recv_buff+index );

    break;

   case WIZ_NEW_CHAR:

    pMain->CreateNewChar( recv_buff+index );

    break;

   case WIZ_DEL_CHAR:

    pMain->DeleteChar( recv_buff+index );

    break;

   case WIZ_SEL_CHAR:

    pMain->SelectCharacter( recv_buff+index );

    break;

   case WIZ_SEL_NATION:

    pMain->SelectNation( recv_buff+index );

    break;

   case WIZ_ALLCHAR_INFO_REQ:

    pMain->AllCharInfoReq( recv_buff+index );

    break;

   case WIZ_LOGOUT:

    pMain->UserLogOut( recv_buff+index );    

    break;

   case WIZ_DATASAVE:

    pMain->UserDataSave( recv_buff+index );

    break;

   case WIZ_KNIGHTS_PROCESS:

    pMain->KnightsPacket( recv_buff+index );

    break;

   case WIZ_CLAN_PROCESS:

    pMain->KnightsPacket( recv_buff+index );

    break;

   case WIZ_LOGIN_INFO:

    pMain->SetLogInInfo( recv_buff+index );

    break;

   case WIZ_KICKOUT:

    pMain->UserKickOut( recv_buff+index );

    break;

   case WIZ_BATTLE_EVENT:

    pMain->BattleEventResult( recv_buff+index );

    break;

   case DB_COUPON_EVENT:

    pMain->CouponEvent( recv_buff+index );

    break;

   }

   recvlen = 0;

   memset( recv_buff, NULL, 1024 );

  }

 }

 

Aujard.exe就分析到这里,至于里面的具体实现

大家还是自己看看吧,这里有我以前分享的骑士online源码资源

我在这里只是把功能结构给大家分析,以便大家更好研究。


点击这里复制本文地址

声明

本站发布所有广告信息、下载资源,均来自互联网,非本站自制,与本站无关。 如有侵犯您的合法权益请来信告之。我们会在三个工作日内予以清除。


本站中所有资料、资源文件均来自于网络搜索,仅作为技术学习研究之用,请必须在24小时内删除所下载文件,切勿用于商业用途,否则由此引发的法律纠纷及连带责任本站和发布者概不承担。


本站保证站内提供的所有可下载资源(软件等等)都是按“原样”提供,本站未做过任何改动;但本网站不保证本站提供的下载资源的准确性、安全性和完整性;同时本网站也不承担用户因使用这些下载资源对自己和他人造成任何形式的损失或伤害。 


访问本站的用户必须明白,[资源爱好者]对提供下载的软件等不拥有任何权利,其版权归该下载资源的合法拥有者所有。


本站所有资源均不提供相关技术服务,如果源码下载地址失效则请联系站长进行补发。


本站所有资源展现图片仅供参考

资源爱好者 © 本站发布所有资源,均来自互联网,非本站自制,分享目的仅供大家学习与参考,与本站无关。
如有侵犯您的合法权益请来信告之。我们会在三个工作日内予以清除。邮箱:admin?aihao.org
关于我们|广告合作|网站地图|冀ICP备14009590号|冀公网安备 13018302000072号