⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 server.cpp

📁 PC网络游戏的编程
💻 CPP
字号:
// server.cpp : Defines the class behaviors for the application.
//

#include "stdafx.h"
#include "server.h"

#include "MainFrm.h"
#include "common.h"
#include "serverDoc.h"
#include "serverView.h"
#include "Clog.h"

#ifdef _DEBUG
#define new DEBUG_NEW
#undef THIS_FILE
static char THIS_FILE[] = __FILE__;
#endif


/////////////////////////////////////////////////////////////////////////////
// CServerApp

BEGIN_MESSAGE_MAP(CServerApp, CWinApp)
	//{{AFX_MSG_MAP(CServerApp)
	ON_COMMAND(ID_APP_ABOUT, OnAppAbout)
		// NOTE - the ClassWizard will add and remove mapping macros here.
		//    DO NOT EDIT what you see in these blocks of generated code!
	//}}AFX_MSG_MAP
	// Standard file based document commands
	//ON_COMMAND(ID_FILE_NEW, CWinApp::OnFileNew)
	//ON_COMMAND(ID_FILE_OPEN, CWinApp::OnFileOpen)
END_MESSAGE_MAP()

/////////////////////////////////////////////////////////////////////////////
// CServerApp construction

CServerApp::CServerApp()
{
	// TODO: add construction code here,
	// Place all significant initialization in InitInstance
}

/////////////////////////////////////////////////////////////////////////////
// The one and only CServerApp object

CServerApp theApp;
CMainFrame *pFrame;

/////////////////////////////////////////////////////////////////////////////
// CServerApp initialization

BOOL CServerApp::InitInstance()
{
	if (!AfxSocketInit())
	{
		AfxMessageBox(IDP_SOCKETS_INIT_FAILED);
		return FALSE;
	}

	// Initialize OLE libraries
	if (!AfxOleInit())
	{
		AfxMessageBox(IDP_OLE_INIT_FAILED);
		return FALSE;
	}

	AfxEnableControlContainer();

	PlayerCount = 0;	
	
	// Standard initialization
	// If you are not using these features and wish to reduce the size
	//  of your final executable, you should remove from the following
	//  the specific initialization routines you do not need.

#ifdef _AFXDLL
	Enable3dControls();			// Call this when using MFC in a shared DLL
#else
	Enable3dControlsStatic();	// Call this when linking to MFC statically
#endif

	// Change the registry key under which our settings are stored.
	// TODO: You should modify this string to be something appropriate
	// such as the name of your company or organization.
	SetRegistryKey(_T("Local AppWizard-Generated Applications"));

	LoadStdProfileSettings();  // Load standard INI file options (including MRU)

	// Register the application's document templates.  Document templates
	//  serve as the connection between documents, frame windows and views.

	CSingleDocTemplate* pDocTemplate;
	pDocTemplate = new CSingleDocTemplate(
		IDR_MAINFRAME,
		RUNTIME_CLASS(CServerDoc),
		RUNTIME_CLASS(CMainFrame),       // main SDI frame window
		RUNTIME_CLASS(CServerView));
	pDocTemplate->SetContainerInfo(IDR_CNTR_INPLACE);
	AddDocTemplate(pDocTemplate);

   	// Parse command line for standard shell commands, DDE, file open
	CCommandLineInfo cmdInfo;
	ParseCommandLine(cmdInfo);

	
	GetCurrentDirectory(MAX_PATH,ch_RunPath);
	// Dispatch commands specified on the command line
	if (!ProcessShellCommand(cmdInfo))
		return FALSE;

	// The one and only window has been initialized, so show and update it.
	m_pMainWnd->ShowWindow(SW_SHOW);
	m_pMainWnd->UpdateWindow();
   
	pFrame = (CMainFrame*)AfxGetMainWnd();
	
	ReadScoreRecordFromFile(GetUniteStr(ch_RunPath,"\\score.txt"));

	CreateServerSocket();
	
	return TRUE;
}


/////////////////////////////////////////////////////////////////////////////
// CAboutDlg dialog used for App About

class CAboutDlg : public CDialog
{
public:
	CAboutDlg();

// Dialog Data
	//{{AFX_DATA(CAboutDlg)
	enum { IDD = IDD_ABOUTBOX };
	//}}AFX_DATA

	// ClassWizard generated virtual function overrides
	//{{AFX_VIRTUAL(CAboutDlg)
	protected:
	virtual void DoDataExchange(CDataExchange* pDX);    // DDX/DDV support
	//}}AFX_VIRTUAL

// Implementation
protected:
	//{{AFX_MSG(CAboutDlg)
		// No message handlers
	//}}AFX_MSG
	DECLARE_MESSAGE_MAP()
};

CAboutDlg::CAboutDlg() : CDialog(CAboutDlg::IDD)
{
	//{{AFX_DATA_INIT(CAboutDlg)
	//}}AFX_DATA_INIT
}

void CAboutDlg::DoDataExchange(CDataExchange* pDX)
{
	CDialog::DoDataExchange(pDX);
	//{{AFX_DATA_MAP(CAboutDlg)
	//}}AFX_DATA_MAP
}

BEGIN_MESSAGE_MAP(CAboutDlg, CDialog)
	//{{AFX_MSG_MAP(CAboutDlg)
		// No message handlers
	//}}AFX_MSG_MAP
END_MESSAGE_MAP()

// App command to run the dialog
void CServerApp::OnAppAbout()
{
	CAboutDlg aboutDlg;
	aboutDlg.DoModal();
}

/////////////////////////////////////////////////////////////////////////////
// CServerApp message handlers

BOOL CServerApp::CreateServerSocket()
{
  MsgBufferCount = 0;
  PlayerAdding       = FALSE;
  cs_Server=new CServerSocket;
  if(cs_Server==NULL)
  {
     WarningBox("Create Sever Socket Failed!");
     return FALSE;
  }
  uint_nPort = 8000;
  cs_Server->Create(uint_nPort);
  GetHostName(ch_HostName);
  GetHostIP(ch_HostAdr);
  ServerLog.AddLogInfoToBuffer("Create Sever Socket Successful");
  ServerLog.AddLogInfoToBuffer(GetUniteStr("Host  IP  : ",ch_HostAdr));
  ServerLog.AddLogInfoToBuffer(GetUniteStr("Host Name : ",ch_HostName));
  ServerLog.AddLogInfoToBuffer(GetUniteStr("Port : ",NumToStr(uint_nPort)));
  cs_Server->Listen();
  ServerLog.AddLogInfoToBuffer("Begin Listening .....");
  return TRUE;
}

void CServerApp::EndServerSocket()
{
  for(int i=0;i<PlayerCount;i++)
  {
    PlayerInfo[i].cs_ClientPtr->Close();
	delete PlayerInfo[i].cs_ClientPtr;
  }
  cs_Server->Close();
  delete cs_Server;
}

int CServerApp::ExitInstance() 
{
	// TODO: Add your specialized code here and/or call the base class
	ServerLog.ClearLogBuffer();
	EndServerSocket();
	return CWinApp::ExitInstance();
}


BOOL CServerApp::AddNewPlayer()
{
	  CReceiveSocket *cs_NewPlayer;
      cs_NewPlayer = new CReceiveSocket;
	  SOCKADDR SockAddr;
	  int int_AddrLen=16;
	  if(cs_Server->Accept(*cs_NewPlayer,&SockAddr,&int_AddrLen))
	  {
		   SockAddrToIPStr(&SockAddr,cs_NewPlayer->ch_PlayerIP);
		   cs_NewPlayer->PlayerNo = PlayerCount;
	       PlayerInfo[PlayerCount].cs_ClientPtr = cs_NewPlayer;        
	       cs_NewPlayer->bo_CreateGame   = FALSE;
           cs_NewPlayer->bo_GameRunning  = FALSE;
	       pFrame->AddPlayerInfoToTable(cs_NewPlayer);
	       PlayerCount++;
	  }
	  else
	  {
		  ServerLog.AddLogInfoToBuffer("New Guest Login Failed ,Server Accept Failed");
	      return FALSE;
	  }
	  return TRUE;
}

BOOL CServerApp::GetNewPlayerName(CReceiveSocket *cs_NewPlayer)
{
    
	LOGIN_INFO rLoginInfo;
    
	//设置列表中的名字
	cs_NewPlayer->Receive(&rLoginInfo,sizeof(LOGIN_INFO),0);
    strcpy(cs_NewPlayer->ch_PlayerName,rLoginInfo.ch_Name);	
	pFrame->SetPlayerNameInTable(cs_NewPlayer);
	
	//发送游戏列表
	SendGameListMsg(cs_NewPlayer,FALSE);
	
	SendNewPlayerToAll(cs_NewPlayer);
	//显示登录成功
	char ch_LogStr[36];
	strcpy(ch_LogStr,cs_NewPlayer->ch_PlayerIP);
    strcat(ch_LogStr," Login Successful");
    ServerLog.AddLogInfoToBuffer(ch_LogStr);
    return TRUE;
}

BOOL CServerApp::DeletePlayer(CReceiveSocket *cs_Player)
{
    
	int PlayerNo = cs_Player->PlayerNo;
	
	//显示玩家离去信息
	char *ch_ShowStr=new char[64];
	strcpy(ch_ShowStr,cs_Player->ch_PlayerIP);
	if(cs_Player->bo_GameRunning)
	{
	   strcat(ch_ShowStr," Run Game and ");
	}
	strcat(ch_ShowStr," Exit ");
	ServerLog.AddLogInfoToBuffer(ch_ShowStr);
	delete[] ch_ShowStr;
	
	pFrame->DeletePlayerInfoFromTable(PlayerNo);
	
	delete cs_Player;
	cs_Player = NULL;
    
	for(int i=PlayerNo;i<PlayerCount-1;i++)
    {
      PlayerInfo[i].cs_ClientPtr = PlayerInfo[i+1].cs_ClientPtr;
	  PlayerInfo[i].cs_ClientPtr->PlayerNo--;
	}
	PlayerCount--;
	return TRUE;
}


BOOL CServerApp::SendPlayerChatMsg(char *ch_ChatMsg,CReceiveSocket *cs_Player)
{
   
	
   int int_MsgSize=*(ch_ChatMsg+1);
   int int_ContentSize = int_MsgSize - 3;
   int int_NameLength=strlen(cs_Player->ch_PlayerName);
   
   int_MsgSize+=(int_NameLength+1); //名字长度加上:长度
   
   char *ch_FullChatMsg=new char[int_MsgSize];
   *(ch_FullChatMsg+0)=MSGTYPE_CHAT;
   *(ch_FullChatMsg+1)=int_MsgSize;
   char *ch_Ptr=ch_FullChatMsg+2;
   strcpy(ch_Ptr,cs_Player->ch_PlayerName);
   ch_Ptr+=int_NameLength;
   strcpy(ch_Ptr,":");
   ch_Ptr+=1;
   memcpy(ch_Ptr,ch_ChatMsg+2,int_ContentSize);
   ch_Ptr+=int_ContentSize;
   strcpy(ch_Ptr,"");
   
   for(int i=0;i<PlayerCount;i++)
   {
      PlayerInfo[i].cs_ClientPtr->Send(ch_FullChatMsg,int_MsgSize,0);
   }
   delete[] ch_FullChatMsg;
   return TRUE;
}

BOOL CServerApp::SendGameListMsg(CReceiveSocket *cs_Client,BOOL bo_ToAll)
{
   
   char *ch_GameList = new char[MAX_MESSAGE];	
   
   char *ch_Ptr      = ch_GameList;
   *(ch_GameList+0)  = MSGTYPE_GAMESERVERLIST;
   ch_Ptr+=2;
   int n = 0;
   int int_IpSize;
   int int_NameSize;
   int i=0;
   CReceiveSocket *cs_OtherPlayer;
   for(i=0;i<PlayerCount-1;i++)
   {
      cs_OtherPlayer = PlayerInfo[i].cs_ClientPtr;  
	  if(cs_OtherPlayer->bo_CreateGame && !cs_OtherPlayer->bo_GameRunning)
	  {
	     int_IpSize   = strlen(cs_OtherPlayer->ch_PlayerIP);
		 int_NameSize = strlen(cs_OtherPlayer->ch_PlayerName);
		 
		 *ch_Ptr = int_IpSize;
		 ch_Ptr++;
		 memcpy(ch_Ptr,cs_OtherPlayer->ch_PlayerIP,int_IpSize+1);
	     ch_Ptr+=int_IpSize;
	     *ch_Ptr = int_NameSize;
		 ch_Ptr++;
		 memcpy(ch_Ptr,cs_OtherPlayer->ch_PlayerName,int_NameSize+1);
		 ch_Ptr+=int_NameSize;
		 n++;
	     if(n>=MAX_GAMESERVER) break;
	  }
    }
    
    if(n==0)
	{
      n=-1;
	}
	*(ch_GameList+1)=n;
    
	int Result=0;
	
	if(bo_ToAll)
	{
	     for(i=0;i<PlayerCount;i++)
		 {
		   Result = PlayerInfo[i].cs_ClientPtr->Send(ch_GameList,strlen(ch_GameList),0);
         }
	}
	else
	{
		Result =  cs_Client->Send(ch_GameList,strlen(ch_GameList),0);
        if(Result == SOCKET_ERROR) 
		{
	     return FALSE;
		}
	}
	return TRUE;
}
	

BOOL CServerApp::HandleMessageBuffer()
{
    for(int i=0;i<MsgBufferCount;i++)
	{
	  char *ch_TempBuffer=MsgBuffer[i].MsgBufferPtr;
	  char MsgType  = *(ch_TempBuffer+0);
	  CReceiveSocket *cs_Player = MsgBuffer[i].cs_Player;
	  switch(MsgType)
	  {
	   case MSGTYPE_GETSCORER:
           {
		       SendScorer(cs_Player);
		       break;
		   }
	   case MSGTYPE_EXIT:
		   {
		       theApp.DeletePlayer(cs_Player);
			   break;
		   }
	   case MSGTYPE_CHAT:
		   {   
		       theApp.SendPlayerChatMsg(ch_TempBuffer,cs_Player);
		       break;
		   }
       case MSGTYPE_RUNGAME:
		   {
		       cs_Player->bo_GameRunning = TRUE;
		       break;
		   }
	   case MSGTYPE_CREATEGAME:
		   {
		       cs_Player->bo_CreateGame = TRUE;
               ServerLog.AddLogInfoToBuffer(GetUniteStr(cs_Player->ch_PlayerIP," Create Game"));
			   theApp.SendGameListMsg(cs_Player,TRUE);
			   break;
		   }
       case MSGTYPE_CANCELGAME:
		   {
		       cs_Player->bo_CreateGame = FALSE;
			   ServerLog.AddLogInfoToBuffer(GetUniteStr(cs_Player->ch_PlayerIP," Cancel Game"));
			   theApp.SendGameListMsg(cs_Player,TRUE);
			   break;
		   }
	  }
	 delete[] ch_TempBuffer;
	}
    MsgBufferCount = 0;
    return TRUE;
}


BOOL CServerApp::GetMessageFromPlayerSocket()
{
   for(int i=0;i<PlayerCount;i++)
   {
      if(!PlayerInfo[i].cs_ClientPtr->bo_MessageReceiving)   
	  {
	     for(int j=0;j<PlayerInfo[i].cs_ClientPtr->MsgBufferCount;j++)
		 {
		    MsgBuffer[MsgBufferCount].MsgBufferPtr = PlayerInfo[i].cs_ClientPtr->MsgBuffer[j];
	        MsgBuffer[MsgBufferCount].cs_Player    = PlayerInfo[i].cs_ClientPtr;
	        MsgBufferCount++;
		 }
	     PlayerInfo[i].cs_ClientPtr->MsgBufferCount = 0;
	  }
   
   }
  return TRUE;
}

BOOL CServerApp::OnIdle(LONG lCount) 
{
	// TODO: Add your specialized code here and/or call the base class
  	if(!PlayerAdding) 
	{
		HandleMessageBuffer();
	    GetMessageFromPlayerSocket();
	}
	return 1;
	//return CWinApp::OnIdle(lCount);
}

void CServerApp::ReadScoreRecordFromFile(char *FileName)
{
    FILE *fp_Score;
	fp_Score = fopen(FileName,"rb");
	int n=0;
	if(fp_Score!=NULL) 
	{
       char PlayerName[MAX_NAME];
	   char Resource[10];
	   char Population[10];
	   char Military[10];
	   while(!feof(fp_Score) && n<MAX_SCORE)
	   {
	     fscanf(fp_Score,"%s",PlayerName);
	     fscanf(fp_Score,"%s",Resource);
	     fscanf(fp_Score,"%s",Population);
	     fscanf(fp_Score,"%s\n",Military);
	     strcpy(ScorerInfo.ScorerName[n],PlayerName);
	     ScorerInfo.Score[n][0] = atol(Resource);
         ScorerInfo.Score[n][1] = atol(Population);
         ScorerInfo.Score[n][2] = atol(Military);
	     n++;
	   }
	   fclose(fp_Score);
	}
	for(int i=n;i<MAX_SCORE;i++)
	{
	     strcpy(ScorerInfo.ScorerName[i],"玩家x");
	     ScorerInfo.Score[i][0] = 1000;
         ScorerInfo.Score[i][1] = 1500;
         ScorerInfo.Score[i][2] = 2000;
	}

}

void CServerApp::SendScorer(CReceiveSocket *cs_Player)
{
    ScorerInfo.MsgType = MSGTYPE_SCORER;
	cs_Player->Send(&ScorerInfo,sizeof(SCORER_INFO),0);
}

void CServerApp::SendNewPlayerToAll(CReceiveSocket *cs_Player)
{
   CReceiveSocket *cs_OtherPlayer;
   char NewPlayerMsg[MAX_NAME+1];
   char *MsgPtr = NewPlayerMsg+1;
   NewPlayerMsg[0]  = MSGTYPE_PLAYERIN;
   strcpy(MsgPtr,cs_Player->ch_PlayerName);
   int n=0;
   for(int i=0;i<PlayerCount-1;i++)
   {
      cs_OtherPlayer = PlayerInfo[i].cs_ClientPtr;  
	  cs_OtherPlayer->Send(NewPlayerMsg,MAX_NAME+1,0);     
	  n++;
	  if(n>=MAX_GAMESERVER) break;
   }
}

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -