这是一个小型多个对战的游戏服务器端代码,经过修改。
文件一:stdafx.h
//-------------------------------------------------------------------------
//stdafx.h中的函数为全局共享
//
//版权所有 DreamShip
//
//-------------------------------------------------------------------------
#ifndef _STDAFX_
#define _STDAFX_
#include
#include
#include
#include
#include
#include
#include "DSGameServer.h"
#include "DSObject.h"
//-------------------------------------------------------------------
// 字符解码调用函数
// 在一串字符中寻找ds_Search中后的数据
// 有浮点型 整形 字符型
//
//
//------------------------------------------------------------------
float DS_ReturnFloat(char *ds_Dest,char ds_Search) ;
int DS_ReturnInt(char *ds_Dest,char ds_Search) ;
int DS_ReturnString(char *ds_Dest,char ds_Search,char *buf ) ;
int DS_ReturnCharPosition( char *ds_Dest,char ds_Search );
//检测当前耗时
void DS_PrintTime( long time );
void DS_GetCurrentTime( char timeBuf[] );
void DS_PrintCurrentTime( char *ds_Msg );
#endif
文件二:stdafx.cpp
//----------------------------------------------------------------------------------
//stdafx.cpp用于全局函数的定义
//
//
//----------------------------------------------------------------------------------
#include "stdafx.h"
//-------------------------------------------------------------------
// 字符解码调用函数
// 在一串字符中寻找ds_Search中后的数据
// 有浮点型 整形 字符型
//
//
//------------------------------------------------------------------
float DS_ReturnFloat(char *ds_Dest,char ds_Search)
{
long time = timeGetTime();
int i=0;
while( ds_Dest[i] != '\0' )
{
if( ds_Dest[i] == ds_Search )
{
int j = 0;
i++;
char buf[50];
while( ds_Dest[i] != '*' )
{
if( ds_Dest[i] =='\0' )
return -100.0f ;
buf[j]=ds_Dest[i] ;
i++ ;
j++ ;
}
buf[j]='\0';
if( buf[0] >= '0' && buf[0] <= '9' )
return (float)atof(buf);
else
return -10000.0f;
}
i++ ;
}
printf("查找不成功所需时间:%d\n",timeGetTime()-time);
return -10000.0f ;
}
//-------------------------------------------------------------------
// 字符解码调用函数
// 在一串字符中寻找ds_Search中后的数据
// 有浮点型 整形 字符型
//
//
//------------------------------------------------------------------
int DS_ReturnInt(char *ds_Dest,char ds_Search)
{
long time = timeGetTime();
int i=0;
while( ds_Dest[i] != '\0' )
{
if( ds_Dest[i] == ds_Search )
{
int j = 0;
i++;
char buf[50];
while( ds_Dest[i] != '*' )
{
if( ds_Dest[i] =='\0' )
return -100 ;
buf[j]=ds_Dest[i] ;
i++ ;
j++ ;
}
buf[j]='\0';
if( buf[0] >= '0' && buf[0] <= '9' )
return atoi(buf);
else
return -10000;
}
i++ ;
}
printf("查找不成功所需时间:%d\n",timeGetTime()-time);
return -10000;
}
//-------------------------------------------------------------------
// 字符解码调用函数
// 在一串字符中寻找ds_Search中后的数据
// 有浮点型 整形 字符型
//
//
//------------------------------------------------------------------
int DS_ReturnString(char *ds_Dest,char ds_Search,char *buf )
{
long time = timeGetTime();
int i=0;
while( ds_Dest[i] != '\0' )
{
if( ds_Dest[i] == ds_Search )
{
int j = 0;
i++;
while( ds_Dest[i] != '*' )
{
if( ds_Dest[i] =='\0' )
return -1 ;
buf[j]=ds_Dest[i] ;
i++ ;
j++ ;
}
buf[j]='\0';
return 1;
}
i++ ;
}
printf("查找不成功所需时间:%d\n",timeGetTime()-time);
return 0;
}
//---------------------------------------------------------------------------
//用于获取当前字符的位置
//
//
//----------------------------------------------------------------------------
int DS_ReturnCharPosition(char *ds_Dest,char ds_Search)
{
long time = timeGetTime();
int i=0;
while( ds_Dest[i] != '\0' )
{
if( ds_Dest[i] == ds_Search )
return i ;
i++ ;
}
printf("查找不成功所需时间:%d\n",timeGetTime()-time);
return -1;
}
//---------------------------------------------------------------------------
//用于测试当前耗时
//
//
//----------------------------------------------------------------------------
void DS_PrintTime( long time )
{
printf( " 程序耗时:%d \n " , timeGetTime()-time );
}
//-------------------------------------------------
//获得当前时间
//
//
//------------------------------------------------------
void DS_GetCurrentTime(char timeBuf[])
{
struct tm *p;
long ltime;
time(<ime);
p=localtime(<ime);
strftime(timeBuf,25,"%a %d %b %Y %H:%M:%S",p);
}
//---------------------------------------------------
//打印当前时间
//
//
//------------------------------------------
void DS_PrintCurrentTime( char *ds_Msg )
{
char buf[29];
struct tm *p;
long ltime;
// _strtime(buf);
// printf("当前时间为:\t\t\t\t%s\n", buf);
// _strdate(buf);
// printf("当前日期为:\t\t\t\t%s\n", buf);
time(<ime);
p=localtime(<ime);
strftime(buf,29,"%a %d %b %Y %H:%M:%S GMT",p);
printf("%s时间:%s\n",ds_Msg,buf);
}
文件三:DSObject.h
//-------------------------------------------------------------
//DSObject.h
// 用于对系统的调度
//
//---------------------------------------------------------------
#ifndef _DSOBJECT_
#define _DSOBJECT_
//DSENEMY 指当前为敌人 DSBULLET 指当前类型为子弹
//DSPLAYER 指当前类型为自已 DSHEAD 指当前类型为头结点
enum OBJECT_TYPE { DSENEMY,DSBULLET,DSPLAYER,DSHEAD,DSNULL};
enum NETOBJECT_TYPE{ DSRED,DSBLUE,DSNETOTHERS,DSNETHEAD,DSNETNULL};
struct D3DXVECTOR3
{
float x ;
float y ;
float z ;
};
class DSObject
{
public :
DSObject( OBJECT_TYPE ds_Type );
DSObject();
~DSObject();
virtual HRESULT DS_InitObject();//用于对象的初始化
virtual void DS_FrameMove( );//用于计算
virtual void DS_RenderScene();//用于渲染
virtual void DS_CleanUp();//清空处理
//用于网络对象的帧刷新
virtual HRESULT DS_NetFrameMove();
//用于该对象的显示
virtual void DS_NetRenderScene();
public:
DSObject *ds_Previous; //前驱结点
DSObject *ds_Next; //后继寻点
OBJECT_TYPE ds_Type; //对象的类型
bool ds_Active;//是否处于存活状态
int ds_Health;//目前的生命值
int ds_ID ;//对象的ID号
NETOBJECT_TYPE ds_NetType ;//其网络类型
char ds_Username[20]; //客户机姓名
float ds_Radius;//碰撞半径
D3DXVECTOR3 ds_CurrentPos;//当前位置
int ds_Score ;//记录当前的战绩
};
#endif
文件四:DSObject.cpp
//-------------------------------------------------------------
//DSObject.cpp
// 用于对系统的调度
// 是DSEnemy DSPlayer DSBullet 的父类
//---------------------------------------------------------------
#include "stdafx.h"
//---------------------------------------------------------------
//函数名:DSObject()
//作用: 为构造函数用于初始化参数
//----------------------------------------------------------------
DSObject::DSObject( OBJECT_TYPE ds_Type )
{
this->ds_Type = ds_Type;
ds_Active = true;
this->ds_NetType = DSNETNULL ;
this->ds_ID = -1000 ;
strcpy(ds_Username,"非网络用户");
ds_Previous = NULL ;
ds_Next = NULL ;
ds_Score = 0 ;
}
//---------------------------------------------------------------
//函数名:DSObject()
//作用: 为构造函数用于初始化网络参数
//----------------------------------------------------------------
DSObject::DSObject()
{
ds_Active = true;
strcpy(ds_Username,"网络用户");
ds_Previous = NULL ;
ds_Next = NULL ;
ds_Score = 0 ;
}
//---------------------------------------------------------------
//函数名:~DSObject()
//作用:析构函数
//----------------------------------------------------------------
DSObject::~DSObject()
{
DS_CleanUp();
}
//---------------------------------------------------------------
//函数名:DS_InitObject()
//作用:
//----------------------------------------------------------------
HRESULT DSObject::DS_InitObject()
{
return S_OK;
}
//---------------------------------------------------------------
//函数名:DS_FrameMove()
//作用:
//----------------------------------------------------------------
void DSObject::DS_FrameMove( )
{
return ;
}
//---------------------------------------------------------------
//函数名:DS_CleanUp()
//作用:
//----------------------------------------------------------------
void DSObject::DS_CleanUp()
{
return ;
}
//---------------------------------------------------------------
//函数名:DS_RenderScene()
//作用:
//----------------------------------------------------------------
void DSObject::DS_RenderScene( )
{
return ;
}
//---------------------------------------------------------------
//函数名:DS_NetFrameMove()
//作用:
//----------------------------------------------------------------
HRESULT DSObject::DS_NetFrameMove()
{
return S_OK ;
}
//----------------------------------------------------------------
//DS_NetRenderScene()
//
//----------------------------------------------------------------
void DSObject::DS_NetRenderScene( )
{
return ;
}
文件五:DSGameServer.h
//-----------------------------------------------------------------------------
// DSGameServer.h
// 用于游戏中的网络通讯架构
//
//------------------------------------------------------------------------------
#ifndef _DSGAMESERVER_
#define _DSGAMESERVER_
//最大上限人数
#define MAX_NUM 150
//开放的端口号
#define DEFAULTPORT 12345
#include "DSObject.h"
//用于客户机信息的绑定
//在此包括客户机的套接字 在运行其间服务器所分配的ID号
//其链接的IP地址 服务器为其分配的发送者线程号
struct dsClientInformation
{
SOCKET ds_Sock ;//当前的套接字
sockaddr_in ds_Client ;//其客户机信息
int ds_ID ;//服务器分配的ID号
DWORD ds_RecvThreadID ;//服务器分配接收的线程号
// DWORD ds_SendThreadID ;//服务器分配的发送线程号
bool ds_Active ;
};
//游戏服务器类
//
class DSGameServer
{
public:
DSGameServer();
~DSGameServer();
int DS_ProcessGameServer( );//用于线程处理
int DS_SendMessage( int ID ,char *buf );//向某一客户机发送信息
int DS_CheckSocket();//检测当前可用的ID号
void DS_CleanSocket( int ID );//清空ID号的套接字
void DS_SendAll( char *buf,int ID = -1 ) ;//向所有的用户发送信息
public:
static DWORD WINAPI DS_ListenThread(void *data);//接收线程
SOCKET ds_ListenSocket; // 等待接收数据的socket
sockaddr_in ds_Server; // 绑定地址
dsClientInformation ds_AcceptSocket[MAX_NUM] ;//客户机的关联消息
//以下是对网络数据的处理
public:
//对内核链表的操作
int DS_AddObject( DSObject *ds_New );
int DS_RemoveObject( DSObject *ds_New );
void DS_Print();
//对网络数据的处理(可能为多流数据所以需要轮循处理)
int DS_ProcessData( char *ds_NetData );
//对所到的数据的识别与解析
int DS_ParseMsgSTC( char *ds_Msg );
//玩家结点的创建与维护
DSObject* DS_PlayerProcess( int ID,char *ds_Msg,int type = 0 );
int DS_CheckState(int ID);//检测当前的状态
public:
DSObject *ds_Head ;//包留头
int ds_EnemyNum ;
int ds_ObjectNum ;
int ds_RedNum ;
int ds_BlueNum ;
int ds_RedCurrentNum ;//记录游戏中为红方的数量
int ds_BlueCurrentNum ;//记录游戏中为蓝方的数量
bool ds_IsPassword ;//是否有密码
char ds_Password[50];//密码
};
#endif
文件六:DSGameServer.cpp
#include "stdafx.h"
DSGameServer *ds_GameDebugServer ;
//-----------------------------------------------------------------------------
//函数名:
//描述:用于系统的初始化
// 主要是Win32通讯的初始化
//
//-----------------------------------------------------------------------------
DSGameServer::DSGameServer()
{
WSADATA wsaData;
//加载当前协议
if(WSAStartup(MAKEWORD(2,2),&wsaData)!=0)
{
printf("无法加载套接字协议栈\n");
return ;
}
//设置侦听套接字
ds_ListenSocket=socket(AF_INET,SOCK_STREAM,0);
if(ds_ListenSocket==INVALID_SOCKET)
{
printf("套接字初始化出现错误;错误号:%d\n",WSAGetLastError());
return ;
}
//设定服务器的信息
ds_Server.sin_family=AF_INET;
ds_Server.sin_port=htons( DEFAULTPORT );
ds_Server.sin_addr.s_addr=htonl(INADDR_ANY);
//对服务器的信息进行绑定
if(bind(ds_ListenSocket,(LPSOCKADDR)&ds_Server,sizeof(ds_Server))==SOCKET_ERROR)
{
printf("绑定出现问题错误号码:%d\n",WSAGetLastError());
return ;
}
//进入侦听状态
if(listen(ds_ListenSocket,5)==SOCKET_ERROR)
{
printf("监听出现问题错误号码:%d\n",WSAGetLastError());
return ;
}
//将所有信息进行初始化
for(int i=0;ids_NetType = DSNETHEAD ;
ds_Head->ds_Type = DSHEAD ;
ds_Head->ds_ID = -1 ;
ds_EnemyNum = 0 ;
ds_ObjectNum = 0;
ds_RedNum = 0 ;
ds_BlueNum = 0 ;
ds_IsPassword = false ;
strcpy(ds_Password,"");
}
//-----------------------------------------------------------------------------
//函数名:析构函数
//描述:用于资源的释放
//
//-----------------------------------------------------------------------------
DSGameServer::~DSGameServer( )
{
if( ds_ListenSocket != NULL )
closesocket( ds_ListenSocket );
WSACleanup();
}
//-----------------------------------------------------------------------------
//函数名:
//描述:用于检测当前没有用的ID号
//
//-----------------------------------------------------------------------------
int DSGameServer::DS_CheckSocket( )
{
for(int i=0;i>>>>>>>>\n新玩家的IP地址为:[%s],端口号:[%d]\n",
inet_ntoa(ds_AcceptSocket[index].ds_Client.sin_addr),
ntohs(ds_AcceptSocket[index].ds_Client.sin_port));
// 提示客户输入密码
char ds_PassBuf[100];
sprintf(ds_PassBuf,"#IP i%d*p0*",ds_AcceptSocket[index].ds_ID );
DS_SendMessage(ds_AcceptSocket[index].ds_ID,ds_PassBuf);
//创建接收者线程
int ThreadID; // 线程id
//调用createthread创建线程
ThreadID = (int)CreateThread(NULL, 0, (LPTHREAD_START_ROUTINE)(DSGameServer::DS_ListenThread), (void *)&ds_AcceptSocket[index], 0, &ds_AcceptSocket[index].ds_RecvThreadID);
ThreadID = ThreadID ? 0 : 1; // 如果成功,则返回为0
if(ThreadID) // ThreadID如果不为0,则线程创建失败
{
printf("线程创建失败\n");
ExitThread(ds_AcceptSocket[index].ds_RecvThreadID );
}
printf("********新玩家ID[%d]的接收线程创建成功*********\n",index );
}
else
{
SOCKET ds_Accept=accept(ds_ListenSocket,(struct sockaddr*)&ds_Client,&ds_Len);
if(ds_Accept==INVALID_SOCKET)
{
printf("连接出现错误代码: %d\n",WSAGetLastError());
break;
}
printf("\n非正常请求的玩家IP地址为:[%s],端口号:[%d]\n",inet_ntoa(ds_Client.sin_addr),
ntohs(ds_Client.sin_port));
send( ds_Accept,"#FF i0*m当前用户已满*",strlen("#FF m当前用户已满 "),0 );
closesocket( ds_Accept );
printf("<<<<<<<<<<非法连接玩家已断开>>>>>>>>>>>>>>..\n");
}
}
return 0;
}
//-----------------------------------------------------------------------------
//函数名:为接收线程
//描述:用select模式对IO进行管理
// 首先判断该线程是否可读 若可读则取出其上的信息
//-----------------------------------------------------------------------------
DWORD WINAPI DSGameServer::DS_ListenThread(void *data)
{
dsClientInformation *ds_GameSocket = (dsClientInformation *)data ;
while(true)
{
if( ds_GameSocket->ds_Sock == NULL )
{
ds_GameDebugServer->DS_CleanSocket( ds_GameSocket->ds_ID );
continue ;
}
//接收数据
char buf[1024] ;
fd_set ds_Read;//基于select模式对IO进行管理
FD_ZERO(&ds_Read);
FD_SET(ds_GameSocket->ds_Sock,&ds_Read);
select(0,&ds_Read,NULL,NULL,NULL) ;
if(FD_ISSET(ds_GameSocket->ds_Sock,&ds_Read) )
{
int result = recv( ds_GameSocket->ds_Sock, buf,sizeof(buf),0 ) ;
if ( result > 0 )
{
buf[result] = 0 ;
printf("\n玩家ID[%d]消息到: %s",ds_GameSocket->ds_ID,buf) ;
ds_GameDebugServer->DS_SendAll(buf,ds_GameSocket->ds_ID) ;
ds_GameDebugServer->DS_ProcessData( buf );
fflush(0) ;
}
else
{
ds_GameDebugServer->DS_CleanSocket( ds_GameSocket->ds_ID );
}
}
}
return 1;
}
//-----------------------------------------------------------------------------
//函数名:用于发送信息
//描述:
//
//-----------------------------------------------------------------------------
int DSGameServer::DS_SendMessage( int ID , char *buf )
{
if( ID<0 )
return 0 ;
printf("向玩家ID%d 发送的信息是:%s\n",ID,buf);
int iSend = send(ds_AcceptSocket[ID].ds_Sock,buf,strlen(buf),0 ) ;
if( iSend == SOCKET_ERROR )//==WSAECONNABORTED || iSend == WSAECONNRESET
{
printf("向ID[%d]发送DS_SendMessage出现错误\n",ID) ;
//DS_CleanSocket( ID );
ds_AcceptSocket[ID].ds_Sock = NULL ;
}
return 1;
}
//----------------------------------------------------
//全发送
//
//----------------------------------------------------
void DSGameServer::DS_SendAll(char *buf,int ID )
{
printf("向全体成员发送:%s\n",buf);
for(int i=0 ; i>>>>>>>>>>\n",ID);
DSObject *p = ds_Head->ds_Next ;
while( p )
{
if( p->ds_ID == ID )
{
printf("正在清空其在内核中的内容\n");
DS_RemoveObject( p );
break ;
}
p = p->ds_Next ;
}
ds_AcceptSocket[ID].ds_Active = false ;
closesocket( ds_AcceptSocket[ID].ds_Sock );
ds_AcceptSocket[ID].ds_Sock = NULL ;
printf("正在关闭他的接收线程为%d\n",ds_AcceptSocket[ID].ds_RecvThreadID );
ExitThread(ds_AcceptSocket[ID].ds_RecvThreadID );
printf("***************************************\n");
printf("<<<<<<<<<<<<<<关闭成功>>>>>>>>>>>>>>>>>>>>>>>\n");
}
//---------------------------------------------------
// 将对象加入系统的链表中
// 第一:找到尾结点
// 第二:将尾结点的next域指向要加入的结点
// 将新结点的previous域指向尾结点
// 第三:若要加入的为敌人对象则敌人的数量加一
// 总的对象数加一
//-----------------------------------------------------------------------
int DSGameServer::DS_AddObject( DSObject *ds_New )
{
if( ds_New == NULL )
return 0;
DSObject *p;
p = ds_Head;
//找到尾结点
while( p->ds_Next != NULL )
p = p->ds_Next ;
// 将尾结点的next域指向要加入的结点
// 将新结点的previous域指向尾结点
p->ds_Next = ds_New ;
ds_New->ds_Previous = p ;
p = NULL ;
free( p );
// 若要加入的为敌人对象则敌人的数量加一
// 总的对象数加一
if( ds_New->ds_Type == DSENEMY )
ds_EnemyNum++;
if(ds_New->ds_NetType == DSRED )
{
ds_RedCurrentNum ++ ;
ds_RedNum ++ ;
}
if(ds_New->ds_NetType == DSBLUE )
{
ds_BlueCurrentNum++ ;
ds_BlueNum ++ ;
}
ds_ObjectNum++;
return 1;
}
//-----------------------------------------------------------------------------
//第一:若当前链表为空 则转到//*************
//第二:若为非空则遍历查找若找到该结点则
// 1.若该结点位于链尾 则 p->ds_Previous->ds_Next = NULL
// 2.若在链表头于尾之间则
// p->ds_Previous->ds_Next = p->ds_Next ;
// p->ds_Next->ds_Previous = p->ds_Previous ;
//第三:若该结点为敌人则敌人数量减一
// 总对象数减一
//-----------------------------------------------------------------------------
int DSGameServer::DS_RemoveObject( DSObject *ds_New )
{
// 若对象这空则
if( ds_New == NULL )
return 0;
DSObject *p;
p = ds_Head->ds_Next ;
//循环查找
while( p != NULL )
{
//如果找到则清空该结点
if( p == ds_New )
{
//若在链表头于尾之间
if(ds_New->ds_Next != NULL )
{
p->ds_Previous->ds_Next = p->ds_Next ;
p->ds_Next->ds_Previous = p->ds_Previous ;
}
//若该结点位于链尾
else
p->ds_Previous->ds_Next = NULL ;
//清空该结点
p->ds_Previous = NULL ;
p->ds_Next = NULL ;
ds_New = NULL ;
//若该结点为敌人对象则
if(p->ds_Type == DSENEMY )
ds_EnemyNum-- ;
if( p->ds_NetType == DSRED )
{
ds_RedCurrentNum --;
ds_RedNum -- ;
}
if( p->ds_NetType == DSBLUE )
{
ds_BlueCurrentNum -- ;
ds_BlueNum -- ;
}
ds_ObjectNum--;
free(p);
return 1 ;
}
p = p->ds_Next ;
}
//******************************
//若当前链表为空 或没找到
free( p );
return 0;
}
//--------------------------------------------------------------------
//打印当前客户信息
//------------------------------------------------------------------
void DSGameServer::DS_Print()
{
DSObject *p;
p = ds_Head->ds_Next ;
printf("ID 类型 生命值 存活 战绩 \n ");
while( p )
{
printf(" %d %d %d %d %d <%f,%f,%f>\n ",p->ds_ID,p->ds_NetType,
p->ds_Health,p->ds_Active, p->ds_Score,p->ds_CurrentPos.x,p->ds_CurrentPos.y,p->ds_CurrentPos.z );
p = p->ds_Next ;
}
p = NULL ;
free(p);
printf("红方:%d 蓝方: %d 总人数: %d\n",ds_RedNum,ds_BlueNum,ds_ObjectNum);
}
//---------------------------------------------------------------------------------
//
//内部解码器
// 用于多发流量的解码
//
//对于所要传输的数据是以#开头,若要在某一缓冲区内接收到了
//多个命令则启动轮循检测以实现数据的准确接收
//
//--------------------------------------------------------------------------------
int DSGameServer::DS_ProcessData( char *ds_NetData )
{
char ds_Dest[1024] ;
strcpy( ds_Dest,ds_NetData );
printf("%s\n",ds_Dest);
while(true)
{
int ds_Count = DS_ReturnCharPosition(ds_Dest,'#');
//查找工作结束
if( ds_Count == -1 )
return 0 ;
char ds_Msg[100] ;
ds_Msg[0] = '#' ;
int count = ds_Count +1 ;
int temp = 1 ;
while( ds_Dest[count] != '#' && ds_Dest[count] != '\0' )
{
ds_Msg[temp++] = ds_Dest[count++] ;
}
ds_Msg[temp] ='\0';
//对命令进行解码
printf("解析的信息为:%s\n",ds_Msg);
if( ds_Msg[temp-1] == '*' )
DS_ParseMsgSTC(ds_Msg);
ds_Dest[ds_Count] = '@';
}
return 1 ;
}
//------------------------------------------------------------------------------------
//检测当前状态
//可能有问题要注意此处的用法
//ID暂时用不到
//------------------------------------------------------------------------------------
int DSGameServer::DS_CheckState(int ID)
{
if(ds_RedNum >0 && ds_BlueNum >0 )
return 0 ;
char send[20];
//如果蓝方胜
if(ds_RedNum <= 0)
sprintf(send,"#ST i0*mBlue Success!*");
//如果红方胜
else if(ds_BlueNum <= 0)
sprintf(send,"#ST i1*mBlue Success!*");
DS_SendAll(send);
//对新一局进行初始化工作
float x = 12.0f ;
float z = 12.0f ;
DSObject *p ;
p = ds_Head->ds_Next ;
while( p )
{
p->ds_Active = true ;
p->ds_Health = 100 ;
srand( timeGetTime() );
p->ds_CurrentPos.y =rand()%3+4.0f ;
if( p->ds_NetType == DSRED )
{
p->ds_CurrentPos.x = x+rand()%20 ;
p->ds_CurrentPos.z = z+rand()%20 ;
}
else
{
p->ds_CurrentPos.x = -x-rand()%20 ;
p->ds_CurrentPos.z = -z-rand()%20 ;
}
p = p->ds_Next ;
}
p = NULL ;
free( p ) ;
printf("执行完成了新一局的初始化\n");
DS_Print();
return 1 ;
}
//----------------------------------------------------------------------------------------
//客户机解码分析器
//主要分析服务器的返回信息
// 首先提取头三个字符进行标头分析
//
//---------------------------------------------------------------------------------------
int DSGameServer::DS_ParseMsgSTC( char *ds_Msg )
{
//第一步校验
//检测数据的长度是否合适 <#DD i0*>
//按照编码要求最小应为7个单位长度
if( strlen(ds_Msg) < 7 )
{
printf("当前没有要处理的信息结构不对\n");
return -2 ;
}
long time = timeGetTime() ;
//提取头三个字符并保存在 ds_Temp 变量中
char ds_Temp[3];
for( int i = 0 ; i<3 ; i++ )
ds_Temp[i] = ds_Msg[i] ;
ds_Temp[3] = '\0' ;
//进入第二步校验 先检测ID号是否正确
int ID ;
if( (ID = DS_ReturnInt(ds_Msg,'i') ) == -10000 )
{
printf("当前要求处理的信息有误ID号不能为-10000\n");
return -2 ;
}
//表示新客户机的信息
//格式为:<#OP i2 x0.32f y2.5f z23.5f t0 uliubing %523667 >
//用务器检测密码若正确则向其传送其他客户机的资料
//并同时向其他客户机传送新机的信息<#NC i3 x12.0f y23.0f z23.02f t1 >
//若错误则断开并发送<#FP 密码错误 >
if( strcmp(ds_Temp ,"#OP" ) == 0 )
{
printf("<<<<<<<<<<<正在进行校验工作>>>>>>>>>>>>>>>>>\n");
//进行密码的校验
if( ds_GameDebugServer->ds_IsPassword )
{
char password[50];
//如果获取密码错误则置为空
if( DS_ReturnString(ds_Msg,'?',password ) == 0 )
strcpy(password,"");
if( strcmp(ds_GameDebugServer->ds_Password,password ) != 0 )
{
ds_GameDebugServer->DS_SendMessage( ID,"#FP i0*m密码错误*");
ds_GameDebugServer->DS_CleanSocket( ID );
return -2 ;
}
}
// 如果通过验证则
// 1更新其在服务器的信息加入内核管理
//2 向其他客户机传送新机消息
//3 向其传送其他客户机消息
DSObject *p ;
if ( ( p = ds_GameDebugServer->DS_PlayerProcess(ID,ds_Msg,1 ) ) == NULL )
{
printf("加入该玩家ID[%d]出现失败\n",ID );
return -2 ;
}
DS_PrintCurrentTime("内核管理打印");
ds_GameDebugServer->DS_Print();
printf("***************************************************\n");
//向其他客户机发送新机器的信息
char ds_NewInfor[300];
sprintf(ds_NewInfor,"#NC i%d*t%d*x%f*y%f*z%f*u%s*",
p->ds_ID,p->ds_NetType,p->ds_CurrentPos.x,
p->ds_CurrentPos.y,p->ds_CurrentPos.z,
p->ds_Username );
ds_GameDebugServer->DS_SendAll( ds_NewInfor,ID );
DS_PrintCurrentTime("向全体发送打印");
ds_GameDebugServer->DS_Print();
printf("***************************************************\n");
//向新玩家发送其他客户机的信息
p = ds_Head->ds_Next ;
while( p )
{
if( p->ds_ID != ID )
{
char ds_NewInfor[300];
sprintf(ds_NewInfor,"#NC i%d*t%d*x%f*y%f*z%f*u%s*h%d*s%d*",
p->ds_ID,p->ds_NetType,p->ds_CurrentPos.x,
p->ds_CurrentPos.y,p->ds_CurrentPos.z,
p->ds_Username,p->ds_Health,p->ds_Score );
ds_GameDebugServer->DS_SendMessage( ID,ds_NewInfor );
ZeroMemory(ds_NewInfor,300);
}
p = p->ds_Next ;
}
p = NULL ;
free( p );
//为可用状态
ds_AcceptSocket[ID].ds_Active = true ;
DS_PrintCurrentTime("向个人打印");
ds_GameDebugServer->DS_Print();
printf("***************************************************\n");
return 1 ;
}
//表示某一玩家要更新信息
//其格式为:<#CU i3*x12.0f*y23.0f*z23.02f*h12*s0*>
//ID号 坐标 当前生命值
//由于网络在设计过程中可能存在一些问题 可能的新用户到时在此这前没有收到故在此
//在进行一次检测
else if( strcmp(ds_Temp ,"#CU" ) == 0 )
{
printf("<<<<<<<<<<<<<<正在进行用户信息刷新工作>>>>>>>>>>>>>>>>>>>>\n") ;
DSObject *p ;
if( ( p = ds_GameDebugServer->DS_PlayerProcess(ID,ds_Msg,0) ) == NULL )
{
printf("更新失败\n");
return -2 ;
}
ds_GameDebugServer->DS_SendAll( ds_Msg,ID );
return 1 ;
}
//表示某一玩家死亡
//其格式为:<#CD i3*s0*>
//ID号 战绩
//将其 Active = false ;
else if( strcmp(ds_Temp ,"#CD" ) == 0 )
{
printf("<<<<<<<<<<<<<<<<<玩家挂了>>>>>>>>>>>>>>>>>>>>>>>>>\n");
DS_Print();
printf("*****************************************************\n");
DSObject *p ;
if( ( p = ds_GameDebugServer->DS_PlayerProcess(ID,ds_Msg,0) ) == NULL )
{
printf("更新失败\n");
return -2 ;
}
p->ds_Health = 0 ;
p->ds_Active = false ;
//此处加上检测当前人数 以便判定那方胜
//应有一个返回类型
ds_GameDebugServer->DS_SendAll( ds_Msg,ID );
//位置应放在这
if (p->ds_NetType == DSRED )
ds_RedNum -- ;
else if(p->ds_NetType == DSBLUE )
ds_BlueNum-- ;
if(ds_RedNum >0 && ds_BlueNum >0 )
return 0 ;
char send[60];
//如果蓝方胜
if(ds_RedNum <= 0)
sprintf(send,"#ST i0*mBlue Success!*");
//如果红方胜
else if(ds_BlueNum <= 0)
sprintf(send,"#ST i1*mRed Success!*");
printf("向全体成员发送:%s\n",send);
for(int i=0 ; ids_Next ;
while( p )
{
p->ds_Active = true ;
p->ds_Health = 100 ;
srand( timeGetTime() );
p->ds_CurrentPos.y =rand()%3+4.0f ;
if( p->ds_NetType == DSRED )
{
p->ds_CurrentPos.x = x+rand()%20 ;
p->ds_CurrentPos.z = z+rand()%20 ;
}
else
{
p->ds_CurrentPos.x = -x-rand()%20 ;
p->ds_CurrentPos.z = -z-rand()%20 ;
}
p = p->ds_Next ;
}
p = NULL ;
free( p ) ;
printf("执行完成了新一局的初始化\n");
DS_Print();
return 1 ;
}
//显示当前被击中 <#HC i0*c0*I8*>
//计算被击中的次数 若损失的生命值大于当前的生命值则死亡
else if( strcmp(ds_Temp,"#HC") == 0)
{
printf("<<<<<<<<<<<<<<<<<<<<<<<某一玩家被击中>>>>>>>>>>>>>>>>>>>>>\n");
ds_GameDebugServer->DS_PlayerProcess(ID,ds_Msg,3);
return 1 ;
}
//表示某一玩家断开连接
//其格式为:<#DD i4 >
//将其所有的消息删除
else if( strcmp(ds_Temp ,"#DD" ) == 0 )
{
printf("<<<<<<<<<<<<<<<<<<<<<<<<玩家ID[%d]要断开连接>>>>>>>>>>>>>>>>>>>>>>>>\n",ID);
//此处应发送此信息
//此处加上检测当前人数 以便判定那方胜
ds_GameDebugServer->DS_CleanSocket( ID ) ;
ds_GameDebugServer->DS_SendAll( ds_Msg,ID ) ;
return 1 ;
}
else if( strcmp(ds_Temp,"#BN") == 0 )
{
//当前在新一局中有客户机信息到
//将要更新的位置信息以#NS处理
DSObject *p ;
p = ds_Head->ds_Next ;
while( p )
{
char ds_NewInfor[300];
sprintf(ds_NewInfor,"#NS i%d*t%d*x%f*y%f*z%f*h%d*s%d*u%s*",
p->ds_ID,p->ds_NetType,p->ds_CurrentPos.x,
p->ds_CurrentPos.y,p->ds_CurrentPos.z,
p->ds_Health,p->ds_Score,p->ds_Username );
ds_GameDebugServer->DS_SendMessage( ID,ds_NewInfor );
ZeroMemory(ds_NewInfor,300);
p = p->ds_Next ;
}
p = NULL ;
free( p );
// 在向其发送可以开局了
ds_GameDebugServer->DS_SendMessage( ID,"#OK i0*" );
return 1 ;
}
//表示当前为聊天信息
//格式:<#CH i0*t0<1><2>*I2*m*你好 >
//0为群发 1为向同伴发送 2为向某一人发送 i为发送方
else if( strcmp(ds_Temp,"#CH" ) == 0 )
{
printf("<<<<<<<<<<<<<<<<<<<<<<<<<聊天信息>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>\n");
return 1 ;
}
return 0 ;
}
//-----------------------------------------------------------------------------------
//玩家结点的创建与维护
//type = 0 ;是对有权限可以对玩家的信息进行更新
//type = 1 ;是对有权限可以对新玩家结点的创建
//type = 2 ; 是对自身结点的创建
//------------------------------------------------------------------------------------
DSObject* DSGameServer::DS_PlayerProcess( int ID,char *ds_Msg,int type )
{
//记数器若找到某一结点则变为1
int count = 0 ;
//将第一个结点
DSObject *p = ds_Head ;
while( p )
{
if( p->ds_ID == ID )
{
count = 1 ;
break ;
}
p = p->ds_Next ;
}
//若找到该结点且可以更新
if( count == 1 && ( type == 1 || type == 0 ) ) //type !=2 && type!=3
{
int ds_tempInt ;//用于保存整形数据
float ds_tempFloat ;//用于保存浮点形数据
//若战绩信息正确则更新 否则不处理
if( ( ds_tempInt = DS_ReturnInt(ds_Msg,'s') ) != -10000 )
p->ds_Score = ds_tempInt ;
//若生命值信息正确则更新 否则不处理
if( ( ds_tempInt = DS_ReturnInt(ds_Msg,'h') ) != -10000 )
p->ds_Health = ds_tempInt ;
//若X位置正确则更新
if( ( ds_tempFloat = DS_ReturnFloat(ds_Msg,'x') ) != -10000.0f )
p->ds_CurrentPos.x = ds_tempFloat ;
//若y位置正确则更新
if( ( ds_tempFloat = DS_ReturnFloat(ds_Msg,'y') ) != -10000.0f )
p->ds_CurrentPos.y = ds_tempFloat ;
//若z位置正确则更新
if( ( ds_tempFloat = DS_ReturnFloat(ds_Msg,'z') ) != -10000.0f )
p->ds_CurrentPos.z = ds_tempFloat ;
return p ;
}
else if( count == 0 && type == 1 )
{
int ds_tempInt ;//用于保存整形数据
float ds_tempFloat ;//用于保存浮点形数据
DSObject *ds_New = new DSObject( );
ds_New->ds_ID = ID ;
//若战绩信息正确则更新 否则不处理
if( ( ds_tempInt = DS_ReturnInt(ds_Msg,'s') ) != -10000 )
ds_New->ds_Score = ds_tempInt ;
//若生命值信息正确则更新 否则不处理
if( ( ds_tempInt = DS_ReturnInt(ds_Msg,'h') ) != -10000 )
ds_New->ds_Health = ds_tempInt ;
//若生命值信息正确则更新 否则不处理
if( ( ds_tempInt = DS_ReturnInt(ds_Msg,'t') ) != -10000 )
ds_New->ds_NetType =(NETOBJECT_TYPE) ds_tempInt ;
//若X位置正确则更新
if( ( ds_tempFloat = DS_ReturnFloat(ds_Msg,'x') ) != -10000.0f )
ds_New->ds_CurrentPos.x = ds_tempFloat ;
//若y位置正确则更新
if( ( ds_tempFloat = DS_ReturnFloat(ds_Msg,'y') ) != -10000.0f )
ds_New->ds_CurrentPos.y = ds_tempFloat ;
//若z位置正确则更新
if( ( ds_tempFloat = DS_ReturnFloat(ds_Msg,'z') ) != -10000.0f )
ds_New->ds_CurrentPos.z = ds_tempFloat ;
if( DS_ReturnString(ds_Msg,'u',ds_New->ds_Username ) == 0 )
strcpy(ds_New->ds_Username,"匿名玩家");
DS_AddObject( ds_New );
// ds_New = NULL ;
//free( ds_New );
return ds_New ;
}
//创建自身的结点
else if( count == 0 && type ==2 )
{
DSObject *ds_Player = new DSObject();
ds_Player->ds_ID = ID ;
ds_Player->ds_NetType = DSRED ;
ds_Player->ds_Type = DSPLAYER ;
DS_AddObject(ds_Player);
return ds_Player ;
}
//用于击中处理
else if( count == 1 && type == 3 )
{
int ds_tempInt ;
if( ( ds_tempInt = DS_ReturnInt(ds_Msg,'c') ) != -10000 )
p->ds_Health -= ds_tempInt*25 ;
p = NULL ;
free( p );
return NULL ;
}
return NULL ;
}
文件七:DSMain.cpp
#include "stdafx.h"
void main()
{
DSGameServer *ds_GameServer = new DSGameServer();
DS_PrintCurrentTime("游戏服务器启动");
printf("*******************DreamShip制作*****************************************\n");
printf("*******************版权所有**********************************************\n");
ds_GameServer->DS_ProcessGameServer();
}
将以上文件保存成源代码,再VC++6.0中进行编译,注意编译之前在Link中加上ws2_32.lib库。