Detailed Implementation |
Implementation For basic network communication, all you have to do is get an instance of RakPeer in your program. These are the most common headers you'll need: |
Headers |
#include "MessageIdentifiers.h" #include "RakPeerInterface.h" #include "RakNetTypes.h" MessageIdentifiers.h contains a giant enumeration representing the native message identifiers that RakNet uses to send you messages, such as disconnection notifications. Since you will probably want to define your own message identifiers, your enumerations should start at the highest enumeration in MessageIdentifiers.h + 1RakPeerInterface.h is an interface for the RakPeer class. RakNetTypes.h defines the structures used in RakNet, including SystemAddress - a unique identifier for systems, and Packet which the API returns to you when you get data or when it needs to send you a message. |
Instancing |
RakNet::RakPeerInterface* peer = RakNet::RakPeerInterface::GetInstance(); That code would give you one instance of the peer. Usually you would only want one of these in a particular exe. The next step is to connect, either as client or as a server. For example: |
Connection as Client |
peer->Startup(1, &SocketDescriptor(), 1) peer->Connect(serverIP, serverPort, 0, 0); The call to Startup starts the network threads. The first parameter is the maximum mumber of connections. For a pure client, we use 1. The second parameter (SocketDescriptor()), specifies the ports/addresses to listen on . Since we want a client, we don't need to specify anything. The call to Connect connects to the server. The first parameter, serverIP, is the IP address or domain of the server. If you want to connect to your own system, such as when running two copies of the same program, use "127.0.0.1" or "localhost" which is accepted notation for your own system. For IPV6, this is "::1". The next parameter in Connect is the serverPort. This is the port you want to try to connect to on the server. If you specify a port the server is not expecting data on you won't be able to connect just like if you had entered the wrong IP. The IP and the port always work together in this fashion to form the complete address. How do you know what port to connect to? Well as the programmer you decide this ahead of time and then just hardcode it into your program. How do you choose a port? You can choose whatever you want as long as no one else is using it and its within the range of 2^16 (0 to 65535). However, certain ports are reserved for use by established programs, such as your web browser, telnet, and FTP. You can look up these port assignments on the internet, but the quick and dirty answer is most ports under 32000 are reserved and ports over 32000 are open to whoever wants them. In practice ports are generally set with #define per program and not changed. For example: #define SERVER_PORT 60005 #define CLIENT_PORT 60006 This way the server will always know what port to respond to and the clients will always know what port to connect to. It also saves end-users the trouble of typing the ports in. Note that connection attempts are asynchronous. The function will return CONNECTION_ATTEMPT_STARTED immediately if it succeeded in the attempt to connect, but it does not mean your connection succeeded. You know your connection succeeded when you call RakPeerInterface::Receive() and a Packet is returned with the first byte ID_CONNECTION_ACCEPTED. You get a network message ID_CONNECTION_ATTEMPT_FAILED when the connection fails. RakNet connects quickly so if you don't connect within a few seconds it's not going to connect. ID_CONNECTION_ATTEMPT_FAILED will be returned to inform you of this. Starting as a server is similar. |
Connection as Server |
peer->Startup(maxConnectionsAllowed, &SocketDescriptor(serverPort,0), 1); The first parameter to Startup is how many simultaneous client connections to allow. The second and third parameter tells what port to listen on. |
Peer to peer connections |
RakNet::SocketDescriptor sd(serverPort,0); peer->Startup(maxConnectionsAllowed, &sd, 1); peer->SetMaximumIncomingConnections(4); Startup sets 10 allowable connections. An allowable connection is either incoming or outgoing. It uses port 60000 to receive data. SetMaximumIncomingConnections is necessary if you want to allow other peers to connect to you, but is not necessary if you only plan to connect to others. In this case, it sets the value to 4. This is a maximum value rather than a reserved value, so it is still possible to say connect to 8 peers - you would then only be able to accept 2 incoming connections until you disconnected from one or more of those peers. |
Reading Packets |
RakNet::Packet *packet = peer->Receive(); RakNet::Packet *packet; namespace RakNet systemAddress specifies the origin of the packet. Every connected system has a unique SystemAddress which is assigned automatically. Note that the system address will be constant over the lifetime of the connection. Certain native network messages use the systemAddress member- for example ID_REMOTE_DISCONNECTION_NOTIFICATION tells you as a client that another client has disconnected. systemAddress in that case specifies which client. UNASSIGNED_SYSTEM_ADDRESS is a reserved value for "Unknown". You should not use systemAddress as a unique identifier for a remote computer. This is because the same computer can have a different systemAddress to every other connection. Use RakNetGUID as a unique identifier for a particular instance of RakPeerInterface. |
Sending Data |
The best way to illustrate sending data is with an example: Twice as many messages get sent out for each higher priority. So if messages of all priorities were waiting to go out, 8 IMMEDIATE_PRIORITY, 4 HIGH_PRIORITY, 2 MEDIUM_PRIORITY, and 1 LOW_PRIORITY would be sent. Obviously however, if only LOW_PRIORITY messages were waiting at all, then those messages would all go out as fast as possible. The sixth parameter (UNASSIGNED_RAKNET_GUID), is the remote system to send to. UNASSIGNED_RAKNET_GUID is a reserved value meaning "no-one in particular". This parameter means one of two things : either who you want to send the packet to, or who you don't want to send the packet to, depending on the value of broadcast, which is the last parameter. |
Shutting Down |
Shutting down is easy and nearly instantaneous. Just call Shutdown() on your peer object, and then destroy it somePeer->Shutdown(300); Shutdown stops the network threads. If you specify a higher than 0 parameter to Shutdown(), Shutdown() will block for up to this amount of time to notify connected systems (if any) to inform them of the connection dropping. 0 will cause a slient Shutdown(), and remote systems will detect the disconnection within about 10 seconds, returning ID_CONNECTION_LOST. |
Cleaning Up |
Just pass the instance that the factory gave you to the DestroyRakPeerInterface. You may want to do this mid-program to free memory but it is not required. RakNet::RakPeerInterface::DestroyInstance(rakPeer); |
See Also |
|
|