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

📄 chost.cpp

📁 <B>DirectX9.0 3D游戏编程</B>
💻 CPP
字号:
/*******************************************************************
 *         Advanced 3D Game Programming using DirectX 9.0
 * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
 * copyright (c) 2003 by Peter A Walsh and Adrian Perez
 * See license.txt for modification and distribution information
 ******************************************************************/
// cHost.cpp: implementation of the cHost class.
//
//////////////////////////////////////////////////////////////////////

#include "cHost.h"
#include "Macros.h"
#include <stdlib.h>
#include <stdio.h>
#include <assert.h>

//////////////////////////////////////////////////////////////////////
// Construction/Destruction
//////////////////////////////////////////////////////////////////////

cHost::cHost() : cMonitor()
{
  unsigned int i;

  for( i = 0; i < PING_RECORDLENGTH; i++ )
  {
    d_pingLink[ i ] = PING_DEFAULTVALLINK;
    d_pingTrans[ i ] = PING_DEFAULTVALTRANS;
  }
  d_ackLength = 0;
  d_bClockTimeSet = false;
}


cHost::~cHost()
{
}


void cHost::SetPort( unsigned short port )
{
  d_port = port;
}


bool cHost::SetAddress( char *pAddress )
{
  if( pAddress == NULL )
    return true;

  IN_ADDR *pAddr;
  HOSTENT *pHe;

  pHe = gethostbyname( pAddress );
  if( pHe == NULL )
    return true;

  pAddr = (in_addr *)pHe->h_addr_list[ 0 ];
  d_address = ntohl( pAddr->s_addr );

  return false;
}


bool cHost::SetAddress( DWORD address )
{
  d_address = address;

  return false;
}


DWORD cHost::GetLastClockTime()
{
  return d_lastClockTime;
}


void cHost::SetLastClockTime( DWORD time )
{
  d_lastClockTime = time;
  d_bClockTimeSet = true;
}
////////////////////////////////////////////////////////////////////////////////

// For qsort
static int sSortPing( const void *arg1, const void *arg2 )
{
  if( *(DWORD *)arg1 < *(DWORD *)arg2 )
    return -1;
  if( *(DWORD *)arg1 > *(DWORD *)arg2 )
    return 1;
  return 0;
}


float cHost::GetAverageLinkPing( float bestPercentage )
{
  if( bestPercentage <= 0.0f ||
      bestPercentage > 100.0f )
    bestPercentage = 100.0f;

  DWORD pings[ PING_RECORDLENGTH ];
  float sum, worstFloat;
  int   worst, i;

  // Recalculate the ping list
  memcpy( pings, &d_pingLink, PING_RECORDLENGTH * sizeof( DWORD ) );
  qsort( pings, PING_RECORDLENGTH, sizeof( DWORD ), sSortPing );

  // Average the first bestPercentage / 100.
  worstFloat = (float)PING_RECORDLENGTH * bestPercentage / 100.0f;
  worst = (int)worstFloat + ( ( worstFloat - (int)worstFloat ) != 0 );
  sum = 0.0f;
  for( i = 0; i < worst; i++ )
    sum += pings[ i ];

  return sum / (float)worst;
}


float cHost::GetAverageTransPing( float bestPercentage )
{
  if( bestPercentage <= 0.0f ||
      bestPercentage > 100.0f )
    bestPercentage = 100.0f;

  DWORD pings[ PING_RECORDLENGTH ];
  float sum, worstFloat;
  int   worst, i;

  // Recalculate the ping list
  memcpy( pings, &d_pingTrans, PING_RECORDLENGTH * sizeof( DWORD ) );
  qsort( pings, PING_RECORDLENGTH, sizeof( DWORD ), sSortPing );

  // Average the first bestPercentage / 100.
  worstFloat = (float)PING_RECORDLENGTH * bestPercentage / 100.0f;
  worst = (int)worstFloat + ( ( worstFloat - (int)worstFloat ) != 0 );
  sum = 0.0f;
  for( i = 0; i < worst; i++ )
    sum += pings[ i ];

  return sum / (float)worst;
}


void cHost::ACKPacket( DWORD packetID, DWORD receiveTime )
{
  cDataPacket *pPacket;

  pPacket = d_outQueue.BorrowPacket( packetID );
  if( pPacket == NULL )
    return;

  DWORD         time;
  unsigned int  i;

  time = receiveTime - pPacket->d_firstTime;
  d_outQueue.ReturnPacket();

  if( pPacket->d_timesSent == 1 )
  {
    for( i = 0; i < PING_RECORDLENGTH - 1; i++ )
      d_pingLink[ i ] = d_pingLink[ i + 1 ];
    d_pingLink[ i ] = time;
  }
  for( i = 0; i < PING_RECORDLENGTH - 1; i++ )
    d_pingTrans[ i ] = d_pingTrans[ i + 1 ];
  d_pingTrans[ i ] = time;

  d_outQueue.RemovePacket( packetID );
}


unsigned short cHost::ProcessIncomingACKs( char *pBuffer, unsigned short len, DWORD receiveTime )
{
  // Get the number of ACKs in this message, not counting the base ACK.
  unsigned char numAcks, mask, *ptr;
  DWORD         basePacketID, ackID;

  ptr = (unsigned char *)pBuffer;

  // Get the base packet ID, which indicates all the ordered packets received so far.
  memcpy( &basePacketID, ptr, sizeof( DWORD ) );
  ptr += sizeof( DWORD );
  // Get the number of additional ACKs.
  numAcks = *ptr;
  ptr++;
  ackID = d_outQueue.GetLowestID();

#if defined( _DEBUG_VERBOSE )
  OUTPUTREPORT3( "<   Ack low=%04d base=%04d end=%04d\n", ackID, basePacketID, basePacketID + numAcks );
#endif

  while( ackID < basePacketID )
  {
    ACKPacket( ackID, receiveTime );
    ackID++;
  }

  mask = 0x80;

  while( ackID < basePacketID + numAcks )
  {
    if( mask == 0 )
    {
      mask = 0x80;
      ptr++;
    }

    if( ( *ptr & mask ) != 0 )
      ACKPacket( ackID, receiveTime );

    mask >>= 1;
    ackID++;
  }

  return ( ptr - (unsigned char *)pBuffer ) + ( mask != 0 );
}


unsigned short cHost::ProcessIncomingReliable( char *pBuffer, unsigned short maxLen, DWORD receiveTime )
{
  // Process any messages in the packet.
  DWORD           packetID;
  char            *readPtr;
  unsigned short  length;

  readPtr = pBuffer;
  memcpy( &packetID, readPtr, sizeof( DWORD ) );
  readPtr += sizeof( DWORD );
  memcpy( &length, readPtr, sizeof( unsigned short ) );
  readPtr += sizeof( unsigned short );
#if defined( _DEBUG_VERBOSE )
  OUTPUTREPORT2( "<   %04d (%d) R\n", packetID, length );
#endif
  // If this message is a packet, queue the data
  // to be dealt with by the application later.
  d_inQueue.AddPacket( packetID, (char *)readPtr, length, receiveTime );
  readPtr += length;


  // Should we build an ACK message?
  if( d_inQueue.GetCount() == 0 )
    return ( readPtr - pBuffer );


  // Build the new ACK message.
  DWORD         lowest, highest, ackID;
  unsigned char mask, *ptr;

  lowest = d_inQueue.GetCurrentID();
  highest = d_inQueue.GetHighestID();

  // Cap the highest so as not to overflow the ACK buffer
  // (or spend too much time building ACK messages).
  if( highest > lowest + ACK_MAXPERMSG )
    highest = lowest + ACK_MAXPERMSG;

#if defined( _DEBUG_VERBOSE )
  OUTPUTREPORT2( " >  %04d ack to %04d ", lowest, highest );
#endif

  ptr = (unsigned char *)d_ackBuffer;
  // Send the base packet ID, which is the ID of the last ordered packet received.
  memcpy( ptr, &lowest, sizeof( DWORD ) );
  ptr += sizeof( DWORD );
  // Add the number of additional ACKs.
  *ptr = highest - lowest;
  ptr++;

  ackID = lowest;
  mask = 0x80;

  while( ackID < highest )
  {
    if( mask == 0 )
    {
      mask = 0x80;
      ptr++;
    }

    // Is there a packet with id 'i' ?
    if( d_inQueue.UnorderedPacketIsQueued( ackID ) == true )
    {
#if defined( _DEBUG_VERBOSE )
  OUTPUTREPORT0( "1" );
#endif
      *ptr |= mask;  // There is
    }
    else
    {
#if defined( _DEBUG_VERBOSE )
  OUTPUTREPORT0( "0" );
#endif
      *ptr &= ~mask;  // There isn't
    }

    mask >>= 1;
    ackID++;
  }

#if defined( _DEBUG_VERBOSE )
  OUTPUTREPORT0( "\n" );
#endif

  // Record the ammount of the ackBuffer used.
  d_ackLength = ( ptr - (unsigned char *)d_ackBuffer ) + ( mask != 0 );

  // return the number of bytes read from 
  return ( readPtr - pBuffer );
}


unsigned short cHost::ProcessIncomingUnreliable( char *pBuffer, unsigned short maxLen, DWORD receiveTime )
{
  // Process any messages in the packet.
  DWORD           packetID;
  char            *readPtr;
  unsigned short  length;

  readPtr = pBuffer;
  memcpy( &packetID, readPtr, sizeof( DWORD ) );
  readPtr += sizeof( DWORD );
  memcpy( &length, readPtr, sizeof( unsigned short ) );
  readPtr += sizeof( unsigned short );
#if defined( _DEBUG_VERBOSE )
  OUTPUTREPORT2( "<   %04d (%d) U\n", packetID, length );
#endif
  // If this message is a packet, queue the data
  // to be dealt with by the application later.
  d_unreliableInQueue.AddPacket( packetID, (char *)readPtr, length, receiveTime );
  readPtr += length;

  // return the number of bytes read from 
  return ( readPtr - pBuffer );
}


unsigned short cHost::AddACKMessage( char *pBuffer, unsigned short maxLen )
{
  if( d_ackLength == 0 )
    return 0;

  unsigned short len;

  len = d_ackLength < maxLen ? d_ackLength : maxLen;

  memcpy( pBuffer, d_ackBuffer, len );

  return len;
}

⌨️ 快捷键说明

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