19.P2P Communication

19.1Concept

Client communication or peer-to-peer networking(hereafter, P2P communication) refers to a direct communication between client hosts without involving a server. This is very useful in the following cases.

  1. Data to be transmitted is too large for a server to handle

  2. Client and server are geographically too distant for a continuous, effective, and low latency networking

  3. Lower latency is required

If players need to synchronize with each other, total amount of traffic server needs to handle is greatly reduced if P2P is used.

그림 19-1Synchronization of players in the characters visual group without using P2P

그림 19-2Synchronization using P2P

However, it must be noted that as number of P2P connections increases, there is a burden on client traffic. Also, there could potentially be an attempt to hack by a malicious player. Critical data should be passed onto the server. ProudNet manages P2P group assembly and disassembly in a server to increase security.

19.2Operation Guide

  1. Server creates a P2P group by a CreateP2PGroup function call.

  2. Clients receive callback indicating newly formed P2P group though INetClientEvent::OnP2PMemberJoin.

  3. Through OnP2PMemberJoin function, each client receives the HostIDs of the clients (members) that have joined in the group.

The following functions are used by a server to manipulate P2P group, and the respective callbacks for clients.

Adding a new member to a P2P group

Delete a member from a P2P group

Delete a P2P group

Example

With a simple addition of few lines, P2P communication can be enabled.

//File Name C2C – Client -
//Client protocol definition file
global C2C 4000 
// client-to-client RMI, 
// The initial messageID = 4000
{
    P2PChat ([in] Proud::StringA txt);
}

Δ PIDL Addition

Server

CNetServer *srv 
         = Proud:: CreateServer();
HostID groupHostID;

Δ Object

// Warning! Do not use GetClientHostIDs
// in the real server.
// Manage them separately. 
HostID list[100];
int listCount = 
        srv->GetClientHostIDs(
             list, 
             100);
  
groupHostID = 
        srv->CreateP2PGroup(
             list, 
             listCount, 
             ByteArray());

Δ P2P group creation

g_S2CProxy.P2PChat(
         groupHostID, 
         RmiContext::ReliableSend,
         L"Hello~~~!");

Δ Communication with a P2P group

srv->DestroyP2PGroup(
       groupHostID);

Δ P2P Group closure

Client

Only the added parts are described here. Previously described parts are omitted.

// Header File Addition
#include “../C2C_Stub.h”
// CPP File Addition
#include “../C2C_Stub.cpp”

Δ Header

client ->AttachProxy(
         &g_C2CProxy);
client ->AttachStub(
         &g_C2CStub);

Δ Server & Client addition

Class CClientEventSink 
       : public INetClientEvent
{
    // Called each time a new member joins
    // to all
    // existing members. 
    virtual void OnP2PMemberJoin(
       HostId memberHostID, 
       HostID groupHostID, 
       int memberCount, 
       const ByteArray &customField) {}
  
    // Called each time a member exits
    // to all existing members. 
    virtual void OnP2PMemberLeave(
        HostID memberHostID, 
        HostID groupHostID, 
        int memberCount) {}
  
    // The rest is omitted. 
}

Δ Event Object - additions

Class C2CStub 
         : public C2C::Stub
{
DECRMI_C2C_P2PChat;
}
DEFRMI_C2C_P2PChat(C2CStub)
{
   Printf(
          “[client] %d, %s”, 
          remote, 
          txt);
}
C2CStub g_C2CStub;

Δ Object to receive C2C communication

C2C::Proxy g_C2CProxy;

Δ Object to send C2C communication

Is the number of transmissions on an unreliable P2P unlimited?

For better performance, using Unreliable is recommended for information (such as Move Packet) that is sent continuously and could be lost.