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

📄 server.cpp

📁 改工程是一个基于select模型实现的MUD游戏
💻 CPP
📖 第 1 页 / 共 2 页
字号:
#define _SERVER_INCLUDE_

#include "XMLEngine.h"


//#include "..\Common Include\CommonInclude.h"


#pragma comment(lib,"ws2_32.lib")

using namespace std;



#define PORT	5050



bool g_bExit=false;


//global functions declaration

void doRecvCmd(vector<SocketInfo>&vecSockInfo,int idx);
void doRecvData(vector<SocketInfo>&vecSockInfo,int idx);
void doExecCmd(_ConnectionPtr,vector<SocketInfo>&vecSockInfo,int idx);
void doAuthen(_ConnectionPtr conn,vector<SocketInfo>&vecSockInfo,int idx);
void doReg(_ConnectionPtr conn,vector<SocketInfo>&vecSockInfo,int idx);
void doInitRole(_ConnectionPtr conn,vector<SocketInfo>&vecSockInfo,int idx);
void doGetRoleInfo(_ConnectionPtr conn,vector<SocketInfo>&vecSockInfo,int idx,char * uName);
void doGetOnLineList(vector<SocketInfo>&vecSockInfo,int idx);
void doGetObjectInfo(CXMLEngine&,vector<SocketInfo>&vecSockInfo,int idx);
void doSaveMessage(vector<SocketInfo>&vecSockInfo,int idx);
void doGetMessage(vector<SocketInfo>&vecSockInfo,int idx);
void doCheckNPC(CXMLEngine&,vector<SocketInfo>&vecSockInfo,int idx);
void doGetNPCInfo(CXMLEngine&,vector<SocketInfo>&vecSockInfo,int idx);
void doUpdateData(_ConnectionPtr conn,vector<SocketInfo>&vecSockInfo,int idx);
void doGetLevelInfo(CXMLEngine&,vector<SocketInfo>&vecSockInfo,int);
void doGetMonsterInfo(CXMLEngine&,vector<SocketInfo>&vecSockInfo,int idx);
void doGetSkillInfo(CXMLEngine&,vector<SocketInfo>&vecSockInfo,int idx);
void doNotice(vector<SocketInfo>&vecSockInfo,int idx);
void doUpdateAfterFight(_ConnectionPtr,vector<SocketInfo>&vecSockInfo,int idx);


_ConnectionPtr CreateConnection(const char *);
bool cmpInDBwithStr(const _ConnectionPtr& connPtr,char* str1,char* str2,DBopCmd);

template<typename T>
void EraseByIndex(vector<T>&vec,int index)
{
	vector<T>::iterator it;
	it=vec.begin()+index;
	vec.erase(it);
}




CXMLEngine xmlEngine("serverdata.xml");

//end global functions declaration



//global var
vector<OnLineList> vecOnLineRoles;
vector<GameMessage> g_vecMessageList;

//end global var

void main()
{
	_ConnectionPtr m_pConnection;


	::CoInitialize(NULL);


	//数据库位置
	char dbSource[10]="my.mdb";


	WSADATA wsd;

	if(WSAStartup(0x0202,&wsd)==0)
	{
		cout<<"服务器正常启动!"<<endl;
	}
	else
	{
		cout<<"WSAStartup() failed"<<endl;
		return;
	}
	
	m_pConnection=CreateConnection(dbSource);


	if(m_pConnection==NULL)
	{
		return;
	}

	vector<SocketInfo> vecSocketInfo;

	SOCKET sListen=socket(AF_INET,SOCK_STREAM,0);


	sockaddr_in serverAddr;
	serverAddr.sin_family=AF_INET;
	serverAddr.sin_addr.s_addr=htonl(INADDR_ANY);
	serverAddr.sin_port=htons(PORT);

	if(bind(sListen,(sockaddr *)&serverAddr,sizeof(serverAddr))==0)
	{
		cout<<"服务器已绑定!"<<endl;
	}
	else
	{
		cout<<"bind failed"<<endl;
		return;
	}


	if(listen(sListen,200)==0)
	{
		cout<<"服务器开始监听!"<<endl;
	}
	else
	{
		cout<<"listen failed"<<endl;
		return;
	}

	SOCKET sockClient;

	FD_SET fdRead;
	FD_SET fdWrite;

	while(!g_bExit)
	{
		FD_ZERO(&fdRead);
		FD_ZERO(&fdWrite);

		FD_SET(sListen,&fdRead);

		for(UINT i=0;i<vecSocketInfo.size();i++)
		{
			FD_SET(vecSocketInfo[i].socket,&fdRead);
			FD_SET(vecSocketInfo[i].socket,&fdWrite);
		}

		if(select(0,&fdRead,&fdWrite,NULL,NULL)==SOCKET_ERROR)
		{
			cout<<"select() failed"<<endl;
			break;
		}


		if(FD_ISSET(sListen,&fdRead))
		{
			char szClientIP[30];
			sockaddr_in clientAddr;
			int calen=sizeof(clientAddr);
			sockClient=accept(sListen,(sockaddr *)&clientAddr,&calen);
			if(sockClient==INVALID_SOCKET)
			{
				cout<<"accept failed"<<endl;
				return;
			}
			
			sprintf(szClientIP,"%s",inet_ntoa(clientAddr.sin_addr));

			cout<<szClientIP<<"连接上来了"<<endl;

			SocketInfo sockInfo;
			memset(&sockInfo,0,sizeof(sockInfo));

			sockInfo.socket=sockClient;
			sockInfo.scurrop=recvCmd;
			sockInfo.isAuthen=false;
			vecSocketInfo.push_back(sockInfo);

		}


		for(UINT i=0;i<vecSocketInfo.size();i++)
		{
			if(FD_ISSET(vecSocketInfo[i].socket,&fdRead))
			{
				switch(vecSocketInfo[i].scurrop)
				{
				case recvCmd:
					doRecvCmd(vecSocketInfo,i);
					break;
				case recvData:
					doRecvData(vecSocketInfo,i);
					break;
				default:
					break;
				}

			}


			if(FD_ISSET(vecSocketInfo[i].socket,&fdWrite))
			{
				switch(vecSocketInfo[i].scurrop)
				{
				case execCmd:
					doExecCmd(m_pConnection,vecSocketInfo,i);
					break;
				default:
					break;
				}
			}
		}
	}


	//关闭数据库,此操作需重新定位
	if(m_pConnection->State)
		m_pConnection->Close();
	m_pConnection=NULL;

}


//处理接受的命令
void doRecvCmd(vector<SocketInfo>&vecSockInfo,int idx)
{
	SocketInfo *sockInfo=&vecSockInfo[idx];

	int nRet=recv(sockInfo->socket,(char*)&sockInfo->scmd,sizeof(sockInfo->scmd),0);
	//如果用户正常登陆,再用closesocket关闭,socket会返回0
	//如果用户直接关闭程序会返回SOCKET_ERROR,强行关闭
	if(nRet==SOCKET_ERROR||nRet==0)
	{
		cout<<"客户端"<<sockInfo->socket<<"已退出!"<<endl;
		/*for(vector<OnLineList>::iterator iter=vecOnLineRoles.begin();iter!=vecOnLineRoles.end();iter++)
		{
			if(strcmp(iter->uName,sockInfo->username)==0)
			{
				vecOnLineRoles.erase(iter);
			}
		}*/
		for(UINT i=0;i<vecOnLineRoles.size();i++)
		{
			if(strcmp(vecOnLineRoles[i].uName,sockInfo->username)==0)
			{
				EraseByIndex(vecOnLineRoles,i);
			}
		}
		sockInfo->socket=INVALID_SOCKET;
		EraseByIndex(vecSockInfo,idx);
		return;
	}

	//有些命令是不需要数据的,在此过滤
	switch(sockInfo->scmd.CommandID)
	{
	case CMD_GETROLEINFO:
		sockInfo->scurrop=execCmd;
		return;
	case CMD_GETOLLIST:
		sockInfo->scurrop=execCmd;
		return;
	case CMD_GETMESSAGE:
		sockInfo->scurrop=execCmd;
		return;
	}

	//没有过滤的都有数据需要接受
	sockInfo->scurrop=recvData;
}


//接受数据函数
void doRecvData(vector<SocketInfo>&vecSockInfo,int idx)
{
	SocketInfo* sockinfo=&vecSockInfo[idx];
	sockinfo->data=new char[sockinfo->scmd.DataSize+1];
	memset(sockinfo->data,0,sockinfo->scmd.DataSize+1);
	

	int nRet=recv(sockinfo->socket,sockinfo->data,sockinfo->scmd.DataSize,0);
	if(nRet==SOCKET_ERROR||nRet==0)
	{
		cout<<"客户端"<<sockinfo->socket<<"已退出!"<<endl;
		for(UINT i=0;i<vecOnLineRoles.size();i++)
		{
			if(strcmp(vecOnLineRoles[i].uName,sockinfo->username)==0)
			{
				EraseByIndex(vecOnLineRoles,i);
			}
		}
		sockinfo->socket=INVALID_SOCKET;
		EraseByIndex(vecSockInfo,idx);
		return;
	}

	sockinfo->scurrop=execCmd;
}

//处理命令函数,命令分发
void doExecCmd(_ConnectionPtr conn,vector<SocketInfo>&vecSockInfo,int idx)
{
	SocketInfo *sockinfo=&vecSockInfo[idx];
	switch(sockinfo->scmd.CommandID)
	{
	case CMD_AUTHEN:
		doAuthen(conn,vecSockInfo,idx);
		break;
	case CMD_REGISTER:
		doReg(conn,vecSockInfo,idx);
		break;
	case CMD_CREATEROLE:
		doInitRole(conn,vecSockInfo,idx);
		break;
	case CMD_GETROLEINFO:
		doGetRoleInfo(conn,vecSockInfo,idx,sockinfo->username);
		break;
	case CMD_GETOLLIST:
		doGetOnLineList(vecSockInfo,idx);
		break;
	case CMD_GETOBJECTINFO:
		doGetObjectInfo(xmlEngine,vecSockInfo,idx);
		break;
	case CMD_SPEAK:
		doSaveMessage(vecSockInfo,idx);
		break;
	case CMD_GETMESSAGE:
		doGetMessage(vecSockInfo,idx);
		break;
	case CMD_CHECKHASNPC:
		doCheckNPC(xmlEngine,vecSockInfo,idx);
		break;
	case CMD_GETNPCINFO:
		doGetNPCInfo(xmlEngine,vecSockInfo,idx);
		break;
	case CMD_UPDATE:
		doUpdateData(conn,vecSockInfo,idx);
		break;
	case CMD_GETLEVELINFO:
		doGetLevelInfo(xmlEngine,vecSockInfo,idx);
		break;
	case CMD_GETMONSTERINFO:
		doGetMonsterInfo(xmlEngine,vecSockInfo,idx);
		break;
	case CMD_GETSKILLINFO:
		doGetSkillInfo(xmlEngine,vecSockInfo,idx);
		break;
	case CMD_NOTICE:
		doNotice(vecSockInfo,idx);
		break;
	case CMD_UPDATEROLEINFO:
		doUpdateAfterFight(conn,vecSockInfo,idx);
		break;
	default:
		break;
	}


	sockinfo->scurrop=recvCmd;
}

void doUpdateAfterFight(_ConnectionPtr conn,vector<SocketInfo>&vecSockInfo,int idx)
{
	SocketInfo* sock=&vecSockInfo[idx];

	player* tplayer=(player*)sock->data;

	char dbcom[512];
	memset(dbcom,0,512);

	sprintf(dbcom,"update role set hp=%d,mp=%d,attack=%d,defendence=%d,celerity=%d,exp=%d,tael=%d,lv=%d,\
		objectnum1=%d,objectnum2=%d,objectnum3=%d,objectnum4=%d,objectnum5=%d,objectnum6=%d,objectnum7=%d,\
		objectnum8=%d,objectnum9=%d,objectnum10=%d where username='%s'",tplayer->hp,tplayer->mp,tplayer->attack,tplayer->defendence,\
		tplayer->celerity,tplayer->exp,tplayer->money,tplayer->level,tplayer->ownObject[0].num,tplayer->ownObject[1].num,\
		tplayer->ownObject[2].num,tplayer->ownObject[3].num,tplayer->ownObject[4].num,tplayer->ownObject[5].num,\
		tplayer->ownObject[6].num,tplayer->ownObject[7].num,tplayer->ownObject[8].num,tplayer->ownObject[9].num,sock->username);

	_variant_t counts;

	conn->Execute(dbcom,&counts,adCmdText);

	if(counts.intVal==1)
	{
		char res[20];
		memset(res,0,20);

		strcpy(res,"UP OK");

		send(sock->socket,res,sizeof(res),0);
	}
	else
	{
		char res[20];
		memset(res,0,20);

		strcpy(res,"UP ERR");

		send(sock->socket,res,sizeof(res),0);

	}


}


//宝物通知信息处理
void doNotice(vector<SocketInfo>&vecSockInfo,int idx)
{
	SocketInfo* sock=&vecSockInfo[idx];
	
	GameMessage mess;
	memset(&mess,0,sizeof(mess));

	char* head="SYS";

	sprintf(mess.message,"%s %s",head,sock->data);

	for(UINT i=0;i<vecOnLineRoles.size();i++)
	{
		strcpy(mess.recver,vecOnLineRoles[i].uName);
		g_vecMessageList.push_back(mess);
	}

}

//获取技能数据
void doGetSkillInfo(CXMLEngine& xmleng,vector<SocketInfo>&vecSockInfo,int idx)
{
	SocketInfo* sock=&vecSockInfo[idx];

	skill sk;
	memset(&sk,0,sizeof(sk));

	if(xmleng.FillWithSkillData(sock->data,sk))
	{
		send(sock->socket,(char*)&sk,sizeof(sk),0);
	}

	delete[] sock->data;
}

//获取怪物信息
void doGetMonsterInfo(CXMLEngine& xmleng,vector<SocketInfo>&vecSockInfo,int idx)
{
	SocketInfo* sock=&vecSockInfo[idx];

	monster mon;
	memset(&mon,0,sizeof(mon));

	if(xmleng.FillWithMonsterInfo(sock->data,mon))
	{
		send(sock->socket,(char*)&mon,sizeof(mon),0);
	}

	delete[] sock->data;
}

//获取等级信息
void doGetLevelInfo(CXMLEngine& xmleng,vector<SocketInfo>&vecSockInfo,int idx)
{
	SocketInfo* sock=&vecSockInfo[idx];
	
	LevelInfo lvi;
	memset(&lvi,0,sizeof(lvi));

	if(xmleng.FillWithLevelInfo(sock->data,lvi))
	{
		send(sock->socket,(char*)&lvi,sizeof(lvi),0);
	}

	delete[] sock->data;

}


//通用更新函数
void doUpdateData(_ConnectionPtr conn,vector<SocketInfo>&vecSockInfo,int idx)
{
	SocketInfo* sock=&vecSockInfo[idx];
	updateNewDS* updata=(updateNewDS*)sock->data;


	char dbcom[256];
	memset(dbcom,0,256);
	switch(updata->opType)
	{
	case DBOP_TYPE_NUM:
		sprintf(dbcom,"update role set %s=%d where username='%s'",updata->op,updata->num,sock->username);
		break;
	case DBOP_TYPE_STRING:
		sprintf(dbcom,"update role set %s='%s' where username='%s'",updata->op,updata->item,sock->username);
		break;
	case DBOP_TYPE_ALL:
		char *pbuf=updata->op;
		char firstop[20],secondop[20];
		memset(firstop,0,20);
		memset(secondop,0,20);
		int index=0;
		while(*pbuf!=' ')
		{
			firstop[index++]=*pbuf++;
		}
		firstop[index]='\0';

		*pbuf++;
		
		index=0;
		while(*pbuf!='\0')
		{
			secondop[index++]=*pbuf++;
		}
		secondop[index]='\0';

		sprintf(dbcom,"update role set %s='%s',%s=%d where username='%s'",firstop,updata->item,secondop,updata->num,sock->username);
		break;
	}


	_variant_t counts;

	conn->Execute(dbcom,&counts,adCmdText);


	if(counts.intVal==1)
	{
		char szSend[20];
		memset(szSend,0,20);
		strcpy(szSend,"UP OK");
		send(sock->socket,szSend,sizeof(szSend),0);
	}
	else
	{

⌨️ 快捷键说明

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