📄 server.cpp
字号:
#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 + -