Player(Loginserver) 分析

// // Player 是指已经通过网络连接进入服务器端程序的客户 // // // #ifndef __PLAYER_H__ #define __PLAYER_H__ #include "Type.h" #include "Socket.h" #include "SocketInputStream.h" #include "SocketOutputStream.h" #include "Packet.h" #define MAX_CACHE_SIZE 1024 //如果在一定时间内没有收到任何消息,则断开此客户端的网络连接 #define MAX_KICK_TIME 300000 //排队消息发送时间 #define MAX_TRUN_MESSAGE_TIME 5000 enum PACKET_FLAG { PF_NONE=0 , PF_REMOVE , }; struct ASYNC_PACKET { Packet* m_pPacket ; PlayerID_t m_PlayerID ; uint m_Flag ; ASYNC_PACKET( ) { m_pPacket = NULL ; m_PlayerID = INVALID_ID ; m_Flag = PF_NONE ; }; ~ASYNC_PACKET( ) { SAFE_DELETE( m_pPacket ) ; m_PlayerID = INVALID_ID ; m_Flag = PF_NONE ; }; }; class Player { public : Player( BOOL bIsServer=FALSE ) ; ~Player( ) ; //从缓冲区中取数据 virtual BOOL ProcessInput( ) ; //打包数据放入缓冲区 virtual BOOL ProcessOutput( ) ; virtual BOOL ProcessCommand( BOOL Option = TRUE ) ; virtual BOOL HeartBeat( UINT uTime=0 ) ; virtual BOOL SendPacket( Packet* pPacket ) ; virtual VOID Encrypt_SC(CHAR* header, UINT uLen, UINT uBeginPlace)=0; virtual VOID DecryptHead_CS(CHAR* header)=0; virtual VOID Decrypt_CS(CHAR* header, UINT uLen, UINT uBeginPlace)=0; public : //通用接口 virtual BOOL IsLoginPlayer( )=0 ; virtual BOOL IsServerPlayer( )=0 ; //用于网通电信互联,判断是不是使用代理服务器的用户和使用哪个代理服务器的用户 //INT WhereThisPlayerFrom(VOID) const; //读取设置玩家PID的接口,PlayerID 是由PlayerPool类分配出来的索引值 //PlayerID用于标识一个客户端连接在整个系统中的数据位置信息 PlayerID_t PlayerID(){ return m_PID ; } ; VOID SetPlayerID( PlayerID_t id ){ m_PID = id ; } ; //读取设置玩家UID的接口,UserID 是由UserPool类分配出来的索引值 //UserID用于标识玩家的游戏存储位置信息 ID_t UserID(){ return m_UID ; } ; VOID SetUserID( ID_t id ){ m_UID = id ; } ; //读取设置玩家PMID的接口,PlayerManagerID 是由PlayerManager类分配出来的索引值 //PlayerManagerID用于标识当前玩家所在的某个PlayerManager中的位置信息,每个 //PlayerManager位于一个独立的线程里。 ID_t PlayerManagerID(){ return m_PlayerManagerID ; } ; VOID SetPlayerManagerID( ID_t id ){ m_PlayerManagerID = id ; } ; //读取当前玩家的Socket类 //网络连接接口 Socket* GetSocket(){ return m_pSocket ; } ; //断开与当前玩家的网络连接 virtual VOID Disconnect( ) ; //判断当前玩家的网络连接是否有效 virtual BOOL IsValid( ) ; //清除当前玩家网络连接数据和缓存数据 virtual VOID CleanUp( ) ; //判断当前玩家数据块是否是空块; //如果是空块,则可以被PlayerPool分配出去用于接收新连接 BOOL IsEmpty( ) { return m_IsEmpty ; } VOID SetEmpty( BOOL opt = TRUE ) { m_IsEmpty = opt ; } BOOL IsDisconnect( ) { return m_IsDisconnect ; } VOID SetDisconnect( BOOL opt = TRUE ) { m_IsDisconnect = opt ; } virtual VOID ResetKick( ) ; private : BOOL m_IsEmpty ; BOOL m_IsDisconnect ; protected : //Player ID //统一由PlayerPool管理 PlayerID_t m_PID ; //User ID //统一由UserPool管理 ID_t m_UID ; //在PlayerManager类中player id数组的下标 ID_t m_PlayerManagerID ; //网络连接句柄 Socket* m_pSocket ; //输入输出数据缓存 SocketInputStream* m_pSocketInputStream ; SocketOutputStream* m_pSocketOutputStream ; BYTE m_PacketIndex ; }; //CHAR* ProxyTool_GetCorrespondingIP(Player const* pPlayer, ID_t ServerID); //UINT ProxyTool_GetCorrespondingPort(Player const* pPlayer, ID_t ServerID); #endif

 

#include "stdafx.h" #include "Player.h" #include "Socket.h" #include "PacketFactoryManager.h" #include "TimeManager.h" #include "Log.h" using namespace Packets ; Player::Player( BOOL bIsServer ) { __ENTER_FUNCTION m_PID = INVALID_ID ; m_UID = INVALID_ID ; m_PlayerManagerID = INVALID_ID ; m_pSocket = new Socket ; Assert( m_pSocket ) ; if( bIsServer ) { m_pSocketInputStream = new SocketInputStream( m_pSocket,DEFAULTSOCKETINPUTBUFFERSIZE,64*1024*1024 ) ; Assert( m_pSocketInputStream ) ; m_pSocketOutputStream = new SocketOutputStream( m_pSocket,DEFAULTSOCKETOUTPUTBUFFERSIZE,64*1024*1024 ) ; Assert( m_pSocketOutputStream ) ; } else { m_pSocketInputStream = new SocketInputStream( m_pSocket ) ; Assert( m_pSocketInputStream ) ; m_pSocketOutputStream = new SocketOutputStream( m_pSocket ) ; Assert( m_pSocketOutputStream ) ; } m_IsEmpty = TRUE ; m_IsDisconnect = FALSE ; m_PacketIndex = 0 ; __LEAVE_FUNCTION } Player::~Player( ) { __ENTER_FUNCTION SAFE_DELETE( m_pSocketInputStream ) ; SAFE_DELETE( m_pSocketOutputStream ) ; SAFE_DELETE( m_pSocket ) ; __LEAVE_FUNCTION } VOID Player::CleanUp( ) { __ENTER_FUNCTION m_pSocket->close() ; m_pSocketInputStream->CleanUp() ; m_pSocketOutputStream->CleanUp() ; SetPlayerManagerID( INVALID_ID ) ; SetUserID( INVALID_ID ) ; m_PacketIndex = 0 ; SetDisconnect(FALSE) ; __LEAVE_FUNCTION } VOID Player::Disconnect( ) { __ENTER_FUNCTION _MY_TRY { m_pSocket->close() ; } _MY_CATCH { } __LEAVE_FUNCTION } BOOL Player::IsValid( ) { __ENTER_FUNCTION if( m_pSocket==NULL ) return FALSE ; if( !m_pSocket->isValid() ) return FALSE ; return TRUE ; __LEAVE_FUNCTION return FALSE ; } BOOL Player::ProcessInput( ) { __ENTER_FUNCTION if( IsDisconnect() ) return TRUE ; _MY_TRY { uint ret = m_pSocketInputStream->Fill( ) ; if( (INT)ret <= SOCKET_ERROR ) { Log::SaveLog( "./Log/LoginError.log", "[%d] m_pSocketInputStream->Fill ret:%d %s", g_pTimeManager->Time2DWORD(), (INT)ret, MySocketError() ) ; return FALSE ; } } _MY_CATCH { return FALSE ; } return TRUE ; __LEAVE_FUNCTION return FALSE ; } BOOL Player::ProcessCommand( BOOL Option ) { __ENTER_FUNCTION BOOL ret ; //包头组成:消息包ID;包大小;包索引,packetuint还不知道干啥用的 CHAR header[PACKET_HEADER_SIZE]; PacketID_t packetID; uint packetuint, packetSize, packetIndex; WORD packetTick; Packet* pPacket = NULL ; if( IsDisconnect( ) ) return TRUE ; _MY_TRY { if( Option ) {//执行部分选项操作 } for( ;; ) { if( !m_pSocketInputStream->Peek(&header[0], PACKET_HEADER_SIZE) ) {//数据不能填充消息头 break ; } this->DecryptHead_CS(header);//封包头解密 //分别获取包头的基本信息 memcpy( &packetID, &header[0], sizeof(PacketID_t) ) ; memcpy( &packetTick, &header[sizeof(WORD)], sizeof(WORD) ) ; memcpy( &packetuint, &header[sizeof(WORD)+sizeof(PacketID_t)], sizeof(uint) ); packetSize = GET_PACKET_LEN(packetuint) ; packetIndex = GET_PACKET_INDEX(packetuint) ; if( packetID >= (PacketID_t)PACKET_MAX ) {//无效的消息类型 Assert( FALSE ) ; return FALSE ; } //消息解密处理--Begin { //获取缓冲区的各个属性 UINT t_uSize = packetSize+PACKET_HEADER_SIZE; UINT t_uHead = m_pSocketInputStream->GetHead(); UINT t_uTail = m_pSocketInputStream->GetTail(); UINT t_uBufferLen = m_pSocketInputStream->GetBuffLen(); CHAR* t_szBuffer = m_pSocketInputStream->GetBuff(); //如果缓冲区的读指针 小于 写指针,数据未读完,写指针还未到缓冲区尾部 if ( t_uHead < t_uTail ) { //缓冲区的起始位置开始,进行包解密,包括包头和包的内容 this->Decrypt_CS(&t_szBuffer[t_uHead], t_uSize, 0); } //否则的话,t_uHead >= t_uTail 可能的情况:写指针已经写到缓冲区尾,然后从缓冲区头开始写,读指针已经读取了一部分数据 else { //计算到缓冲区尾还有多少数据没有读 UINT rightLen = t_uBufferLen - t_uHead ; //如果到缓冲区尾部已经有足够的数据可读,那么开始解密;否则,解密完这部分数据后,再从缓冲区头开始解密其他部分的数据 if( t_uSize <= rightLen ) { this->Decrypt_CS(&t_szBuffer[t_uHead], t_uSize, 0); } else { this->Decrypt_CS(&t_szBuffer[t_uHead], rightLen, 0); this->Decrypt_CS(t_szBuffer, t_uSize-rightLen, rightLen); } } } //消息解密处理--End _MY_TRY { //如果缓冲区内的数据的大小还没一个包数据的大小,则表示数据没有接完,等待套接字数据 if( m_pSocketInputStream->Length()<PACKET_HEADER_SIZE+packetSize ) {//消息没有接收全 break; } if( packetSize>g_pPacketFactoryManager->GetPacketMaxSize(packetID) ) {//消息的大小出现异常,收到的消息比预定义消息的最大值还要大 Assert( FALSE ) ; // m_pSocketInputStream->Skip( PACKET_HEADER_SIZE+packetSize ) ; return FALSE ; } //使用工厂方法的设计模式,创建一个包的产品实例 Packet* pPacket = g_pPacketFactoryManager->CreatePacket( packetID ) ; if( pPacket==NULL ) {//不能分配到足够的内存 Assert( FALSE ) ; // m_pSocketInputStream->Skip( PACKET_HEADER_SIZE+packetSize ) ; return FALSE ; } //设置消息序列号 pPacket->SetPacketIndex( packetIndex ) ; ret = m_pSocketInputStream->ReadPacket( pPacket ) ; if( ret==FALSE ) {//读取消息内容错误 Assert( FALSE ) ; g_pPacketFactoryManager->RemovePacket( pPacket ) ; return FALSE ; } BOOL bNeedRemove = TRUE ; _MY_TRY { //修正m_KickTime信息,m_KickTime信息中的值为判断是否需要踢掉 //客户端的依据 this->ResetKick( ) ; //此处玩家处理客户端的包需求的行为,一切都是为了这个目的 uint uret = pPacket->Execute( this ) ; if( uret==PACKET_EXE_ERROR ) {//出现异常错误,断开此玩家连接 if( pPacket ) g_pPacketFactoryManager->RemovePacket( pPacket ) ; return FALSE ; } else if( uret==PACKET_EXE_BREAK ) {//当前消息的解析执行将停止 //直到下个循环时才继续对缓存中的数据进行消息格式 //化和执行。 //当需要将客户端的执行从一个场景转移到另外一个场景时: //需要在发送转移消息后将执行在本线程中停止。 if( pPacket ) g_pPacketFactoryManager->RemovePacket( pPacket ) ; break ; } else if( uret==PACKET_EXE_CONTINUE ) {//继续解析剩下的消息 } else if( uret==PACKET_EXE_NOTREMOVE ) {//继续解析剩下的消息,并且不回收当前消息 bNeedRemove = FALSE ; } else if( uret == PACKET_EXE_NOTREMOVE_ERROR ) { return FALSE ; } else {//未知的返回值 Assert(FALSE) ; } } _MY_CATCH { } if( pPacket && bNeedRemove ) g_pPacketFactoryManager->RemovePacket( pPacket ) ; } _MY_CATCH { return FALSE; } } } _MY_CATCH { } return TRUE ; __LEAVE_FUNCTION return FALSE ; } BOOL Player::ProcessOutput( ) { __ENTER_FUNCTION if( IsDisconnect( ) ) return TRUE ; _MY_TRY { uint size = m_pSocketOutputStream->Length() ; if( size==0 ) { return TRUE ; } uint ret = m_pSocketOutputStream->Flush( ) ; if( (INT)ret <= SOCKET_ERROR ) { Log::SaveLog( "./Log/LoginError.log", "[%d] m_pSocketOutputStream->Flush ret:%d %s", g_pTimeManager->Time2DWORD(), (INT)ret, MySocketError() ) ; return FALSE ; } } _MY_CATCH { return FALSE ; } return TRUE ; __LEAVE_FUNCTION return FALSE ; } BOOL Player::SendPacket( Packet* pPacket ) { __ENTER_FUNCTION //判断套接字连接是否正常 if( IsDisconnect( ) ) return TRUE ; if( m_pSocketOutputStream!=NULL ) { //设置包索引 pPacket->SetPacketIndex( m_PacketIndex++ ) ; //设置包ID PacketID_t packetID = pPacket->GetPacketID() ; UINT w; //包ID是否合法,如果是,则先向缓冲区中写入包分隔符 if ( packetID < PACKET_LC_MAXCOUNT) { w = m_pSocketOutputStream->Write( PACK_COMPART , PACK_COMPART_SIZE ) ; } //获取缓冲区的写指针的位置,作为开始写的位置 UINT t_uTail_Begin = m_pSocketOutputStream->GetTail();//查询当前包尾位置。记录写包前位置 //先写入包头的包ID w = m_pSocketOutputStream->Write( (CHAR*)&packetID , sizeof(PacketID_t) ) ; //获取时间戳,并写入缓冲区 WORD packetTick = g_pTimeManager->RunTick(); w = m_pSocketOutputStream->Write( (CHAR*)&packetTick , sizeof(WORD) ) ; //再继续写入包索引和包大小 UINT packetUINT ; UINT packetSize = pPacket->GetPacketSize( ) ; UINT packetIndex = pPacket->GetPacketIndex( ) ; SET_PACKET_INDEX(packetUINT, packetIndex) ; SET_PACKET_LEN(packetUINT, packetSize) ; w = m_pSocketOutputStream->Write( (CHAR*)&packetUINT, sizeof(UINT) ) ; //向缓冲区写入包的内容 BOOL ret = pPacket->Write( *m_pSocketOutputStream ) ; UINT t_uTail_End = m_pSocketOutputStream->GetTail();//查询当前包尾位置。记录写包后位置 //消息加密处理--Begin { //分别计算缓冲区的属性 //数据大小,写指针位置,读指针位置,缓冲区长度,缓冲区指针 UINT t_uSize = t_uTail_End - t_uTail_Begin; UINT t_uHead = m_pSocketOutputStream->GetHead(); UINT t_uTail = m_pSocketOutputStream->GetTail(); UINT t_uBufferLen = m_pSocketOutputStream->GetBuffLen(); CHAR* t_szBuffer = m_pSocketOutputStream->GetBuff(); //加密 if ( t_uHead < t_uTail ) { this->Encrypt_SC(&(t_szBuffer[t_uTail_Begin]), t_uSize, 0); } else { UINT rightLen = t_uBufferLen - t_uHead ; //包加密 if( t_uSize <= rightLen ) { this->Encrypt_SC(&(t_szBuffer[t_uTail_Begin]), t_uSize, 0); } else { this->Encrypt_SC(&(t_szBuffer[t_uTail_Begin]), rightLen, 0); this->Encrypt_SC(t_szBuffer, t_uSize-rightLen, rightLen); } } } //消息加密处理--End //BOOL ret = m_pSocketOutputStream->WritePacket( pPacket ) ; Assert( ret ) ; //Log::SaveLog( "./Log/LoginDebug.log", "SendPacket! SOCKET=%d, ID=%d", // m_pSocket->getSOCKET(), pPacket->GetPacketID() ) ; } return TRUE ; __LEAVE_FUNCTION return FALSE ; } BOOL Player::HeartBeat( UINT uTime ) { __ENTER_FUNCTION return TRUE ; __LEAVE_FUNCTION return FALSE ; } VOID Player::ResetKick( ) { __ENTER_FUNCTION __LEAVE_FUNCTION } //INT Player::WhereThisPlayerFrom(VOID) const //{ // if(NULL!=m_pSocket) // { // return g_Config.m_InternalIpofProxy.WhereThisIpFrom(m_pSocket->m_Host); // } // return INVALID_ISP; //} //CHAR* ProxyTool_GetCorrespondingIP(Player const* pPlayer, ID_t ServerID) //{ // __ENTER_FUNCTION // _SERVER_DATA* pData = g_pServerManager->FindServerInfo( ServerID ); // if(NULL==pData) // { // CHAR szLog[1024]; // tsnprintf(szLog, sizeof(szLog), "[ProxyTool_GetCorrespondingIP] Error: Can't found the specific server(%d).", ServerID); // szLog[sizeof(szLog)-1] = '/0'; // AssertEx(pData, szLog); // } // INT nIsp = pPlayer->WhereThisPlayerFrom(); // if(INVALID_ISP==nIsp) // { // return pData->m_IP0; // } // else // { // if(TRUE==RangeCheckForIndex_Assert(nIsp, 0, NUM_OF_ISP-1, "ProxyTool_GetCorrespondingIP")) // { // PROXY_DATA& rProxy = pData->m_aProxy[nIsp]; // if(TRUE==rProxy.m_bEnabled) // { // return rProxy.m_szIP; // } // return pData->m_IP0; // } // else // { // return pData->m_IP0; // } // } // __LEAVE_FUNCTION // return NULL; //} //UINT ProxyTool_GetCorrespondingPort(Player const* pPlayer, ID_t ServerID) //{ // __ENTER_FUNCTION // _SERVER_DATA* pData = g_pServerManager->FindServerInfo( ServerID ); // if(NULL==pData) // { // CHAR szLog[1024]; // tsnprintf(szLog, sizeof(szLog), "[ProxyTool_GetCorrespondingPort] Error: Can't found the specific server(%d).", ServerID); // szLog[sizeof(szLog)-1] = '/0'; // AssertEx(pData, szLog); // } // INT nIsp = pPlayer->WhereThisPlayerFrom(); // if(INVALID_ISP==nIsp) // { // return pData->m_Port0; // } // else // { // if(TRUE==RangeCheckForIndex_Assert(nIsp, 0, NUM_OF_ISP-1, "ProxyTool_GetCorrespondingIP")) // { // PROXY_DATA& rProxy = pData->m_aProxy[nIsp]; // if(TRUE==rProxy.m_bEnabled) // { // return rProxy.m_nPort; // } // return pData->m_Port0; // } // else // { // return pData->m_Port0; // } // } // __LEAVE_FUNCTION // return NULL; //}

 

此类主要是用来加密,解密,处理数据包

你可能感兴趣的:(function,socket,解密,header,null,delete)