首页 诗词 字典 板报 句子 名言 友答 励志 学校 网站地图
当前位置: 首页 > 教程频道 > 开发语言 > C++ >

游戏服务器端通讯框架(C++与Socket)

2013-03-21 
游戏服务器端通信框架(C++与Socket)  这是一个小型多个对战的游戏服务器端代码,经过修改。文件一:stdafx.h/

游戏服务器端通信框架(C++与Socket)

  这是一个小型多个对战的游戏服务器端代码,经过修改。

文件一:stdafx.h

//-------------------------------------//stdafx.h中的函数为全局共享////版权所有 DreamShip////-------------------------------------#ifndef _STDAFX_#define _STDAFX_#include <stdio.h>#include <stdlib.h>#include <string.h>#include <iostream.h>#include <winsock2.h>#include<time.h>#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);elsereturn -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);elsereturn -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(&ltime);p=localtime(&ltime);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(&ltime);p=localtime(&ltime);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;        // 等待接收数据的socketsockaddr_in ds_Server;// 绑定地址dsClientInformation ds_AcceptSocket[MAX_NUM] ;//客户机的关联消息//以下是对网络数据的处理public://对内核链表的操作    intDS_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;i<MAX_NUM;i++)ds_AcceptSocket[i].ds_Sock = NULL;   printf("网络通讯初始化成功\n");ds_GameDebugServer = this ;if( ds_GameDebugServer == NULL ){printf("当前创建Server出错\n");    return ;}ds_Head = new DSObject() ;    ds_Head->ds_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<MAX_NUM;i++){if( ds_AcceptSocket[i].ds_Sock == NULL )return i;}return -1;} //--------------------------------////描述:为每一个新加入的玩家创建一个接收线程//      同时若人数达到上限 则进入相应的处理////------------------------------------int DSGameServer::DS_ProcessGameServer(){    while(true){ //获取当前可用的套接字 int index = DS_CheckSocket(); sockaddr_in ds_Client ;//非正常的客户信息  int ds_Len = sizeof( ds_Client );  if( index != -1 ) {              ds_AcceptSocket[index].ds_Sock=accept(ds_ListenSocket,(struct sockaddr*)&ds_AcceptSocket[index].ds_Client,&ds_Len);ds_AcceptSocket[index].ds_ID = index ;ds_AcceptSocket[index].ds_Active = false ;//用以标识是否为经过校验if( ds_AcceptSocket[index].ds_Sock == INVALID_SOCKET ){printf("连接出现错误代码: %d\n",WSAGetLastError());break;}printf("\n<<<<<<<<<<<<<<有新玩家到>>>>>>>>>\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<MAX_NUM ; i++ ){if( ds_AcceptSocket[i].ds_Sock != NULL && i != ID && ds_AcceptSocket[ID].ds_Active )DS_SendMessage(i,buf);}}//-----------------------------//用于对象的清空处理////------------------------------void DSGameServer::DS_CleanSocket( int ID ){if( ID < 0 )return ;char send[20];sprintf(send,"#DD i%d*",ID);DS_SendAll( send,ID );  printf("<<<<<<<<<<<<玩家[%d]退出游戏>>>>>>>>>>>\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   类型  生命值  存活  战绩 <x   y   z  > \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 ; i<MAX_NUM ; i++ )  {if( ds_AcceptSocket[i].ds_Sock != NULL )DS_SendMessage(i,send);  }  printf("***************%s***********\n",send);  //对新一局进行初始化工作  float x = 12.0f ;  float z = 12.0f ;  p = NULL ;  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 ;}//显示当前被击中 <#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库。


热点排行