Cogito, ergo sum

Legacy:UDP Server Sample

From Unreal Wiki, The Unreal Engine Documentation Site
Jump to: navigation, search

Well, this is my first contribution....If I made some mistakes feel free to correct them :) - Matthieu29 -

This sample code show how to run an Wikipedia:UDP server for UT2003.

UDP is a connection-less protocol, this means that there's no establisched connection between the client and server. Packets might get lost or might be received in random order. Also the remote side is not validated, there's no way to assure that the packet came from the host as reported by the packet (spoofing IP's). The only check that is performed on UDP packets is if the content is valid (CRC checksum). If the content is invalid the packet is dropped as if it was never send. Because of all this UDP provides as fast way to communicate. UDP is often used in applications where it doesn't matter much that data might get lost: game servers, streaming video, VoIP. UDP also has a limitation the the maximum data because packet fragmentation is not supported. You can't send UDP packets larger that the MTU (which is often 1500), using 1000 bytes as a maximum length is usualy a good choice.

This class create, an UDP server socket to receive datas from an external program. You just have to specify the port number (a default properties), the IP address used id the local one : 127.0.0.1. I originally designed this class to use a 3D tracker (mounted on a virtual reality helmet) in order to set virtual player's pitch roll and yaw.

First, the class extracts 6 chars sended by the external program: the pitch yaw and roll composing player's head rotation. (Each of the 3 angles are coded with 2 chars).

After, an another class of the game gets these informations in order to set the virtual player's rotation.

Class MyUdp extends UdpLink;
 
var int iPort;   // server port number
var int pitch;
var int yaw;
var int roll;
 
function InitUdpLinkTracker()
  {
  local string address; // contains the address (for debug purposes)
  local IpAddr Addr;    // struct with the address and the port of the client (us)
 
  log("InitUdpLinkTracker (entered)");
 
  ReceiveMode = RMODE_Event; // We are using events to catch incomming datas
  LinkMode = MODE_Text;      // We expect to receive datas in text format
 
  // set the socket
  GetLocalIp(Addr);
  addr.port = iport;
  address = ipaddrtostring(Addr);
  log ("Address: "$address);
 
  // bind
  if (BindPort(addr.port, true) > 0)
    {
    log("bind OK : socket initialized and binded!");
 
    address = ipaddrtostring(Addr);
    log ("Addr"$address);
    }
  else log("### bind ERROR!");
}
 
event ReceivedText (IpAddr Addr, string Text)
{
// we have just received a string !
 
log("Read string: "$Text$" Size : "$Len(Text));
 
//convert the 6 read chars into three 32 bits int (2 chars => 2X8 bits)
  pitch = Asc(Right(Text,len(Text)-1)) + 256 * Asc(Right(Text,len(Text)));
  yaw  = Asc(Right(Text,len(Text)-3)) + 256 * Asc(Right(Text,len(Text)-2));
  roll = Asc(Right(Text,len(Text)-5)) + 256 * Asc(Right(Text,len(Text)-4));
 
log(" pitch read "$pitch);
log(" yaw read "$yaw);
log(" roll read "$roll);
}
 
 
defaultproperties
  {
  iPort=4000     // local port number
  }

As I explained, the server port number is set by "iPort", and the IP adress of the server is the IP of the local machine.

"ReceivedText" is called when you have received datas.

After, pitch yaw and roll are acessed by an another class so I can change the player's rotation ! :)

So, let's see how to use it:

class MyXPlayer extends XPlayer
    DependsOn(xUtil) config(user);
 
var MyTcp UdpComm;      // class member for UDP communication (UDP communication used to set the rotation of the player)
 
// Initialize the UDP comunication class
simulated event PostBeginPlay()
  {
  Super.PostBeginPlay(); // call the super
  UdpComm=Spawn(class'MyUdp');   // Here we spawn the MyUDP class
  UdpComm.InitUdpLinkTracker();  // Here we initilalize the UDP connection
  }
 
//Function "PlayerTick" called every DeltaTime T
event PlayerTick( float DeltaTime )
  {
  Super.PlayerTick(DeltaTime); // call the super
  SetRotationOfPlayer(UdpComm.pitch, UdpComm.yaw, UdpComm.roll);
  }
 
// set the rotation of the player!
simulated function SetRotationOfPlayer(int ClientPitch, int ClientYaw, int ClientRoll)
{
local rotator PlayerRotate;
 
  PlayerRotate.Pitch = ClientPitch;
  PlayerRotate.Yaw   = ClientYaw;
  PlayerRotate.Roll  = ClientRoll;
  SetRotation(PlayerRotate); //apply the rotation
}
 
replication
  {
  reliable if ( Role == ROLE_Authority )
  SetRotationOfPlayer();
  }