# Using P2P communication

## Simple to use

You can perform P2P communication with a simple code addition.

### - Example of adding PIDL

See [PIDL](https://docs.proudnet.com/proudnet.eng/proudnet/using_pn/pidl) for more usage examples.

```
//File Name between C2C – Client 
//The definition file for the Protocol.

// client-to-client RMI, 
// Initial message ID = 4000
global C2C 4000 
{
    P2PChat ([in] Proud::StringA txt);
}
```

### - Server

{% tabs %}
{% tab title="C++" %}
Object

<pre class="language-cpp"><code class="lang-cpp">Proud::CNetServer *srv 
         = Proud::CNetServer::Create();
<strong>Proud::HostID groupHostID;
</strong></code></pre>

&#x20;Creating a P2P group

```cpp
// Caution! Do not use GetClientHostIDs 
// on the actual server, 
// manage them separately.
Proud::HostID list[100];
int listCount = 
        srv->GetClientHostIDs(
             list, 
             100);
  
groupHostID = 
        srv->CreateP2PGroup(
             list, 
             listCount, 
             ByteArray());
```

&#x20;

Sending communications to P2P groups

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

&#x20;

Destroying a P2P Group

```cpp
srv->DestroyP2PGroup(groupHostID);
```

{% endtab %}

{% tab title="C#" %}
Object

<pre class="language-csharp"><code class="lang-csharp"><strong>Nettention.Proud.NetServer srv = new Nettention.Proud.NetServer();
</strong>Nettention.Proud.HostID groupHostID;
</code></pre>

&#x20;

&#x20;Creating a P2P group

<pre class="language-csharp"><code class="lang-csharp">// Caution! Do not use GetClientHostIDs 
// on the actual server, 
// manage it separately.
<strong>Nettention.Proud.HostID[] list = srv.GetClientHostIDs();
</strong>
groupHostID = srv.CreateP2PGroup(
             list,
             new Nettention.Proud.ByteArray());
</code></pre>

Sending communications to P2P groups

```csharp
g_S2CProxy.P2PChat(
         groupHostID, 
         Nettention.Proud.RmiContext.ReliableSend,
         "Hello~~~!");
```

Destroying a P2P Group

```csharp
srv.DestroyP2PGroup(groupHostID);
```

{% endtab %}
{% endtabs %}

### - Client

Omit them except where they are used additionally.

{% tabs %}
{% tab title="C++" %}
**Header**

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

&#x20;

**What needs to be added to the Server & Client structure**

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

&#x20;

**Event object - the part that is used additionally**

```cpp
Class CClientEventSink : public INetClientEvent
{
       // This will be called 
       // as many times as there are members 
       // in the newly added Group.
       virtual void OnP2PMemberJoin(
           HostID memberHostID, 
           HostID groupHostID, 
           int memberCount, 
           const ByteArray &customField) {}
  
       // This will be called as many times as  
       // there are Members being removed.
       virtual void OnP2PMemberLeave(
           HostID memberHostID, 
           HostID groupHostID, 
           int memberCount) {}
  
       // Other omissions
}
```

**Objects for receiving C2C communication**

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

&#x20;

**Objects for sending C2C communications**

```cpp
C2C::Proxy g_C2CProxy;
```

{% endtab %}

{% tab title="C#" %}
**namespace**

```csharp
using namespace ChatC2C;
```

**What needs to be added to the Server & Client structure**

```csharp
//Attach proxy,stubs to the client.
//Caution!!! This will not work without attach.
netClient.AttachProxy(c2cProxy);
netClient.AttachStub(c2cStub);
```

{% endtab %}
{% endtabs %}

{% hint style="warning" %}
It is efficient to use **Unreliable** for information that you send frequently and can afford to lose, such as **Move Packets**.

* **Client with hole punched**\
  It uses **Reliable UDP** internally, but retransmissions occur, which can also increase traffic.<br>
* **Clients with incomplete hole punching**\
  The server communicates through Relay, where **Unreliable** communicates with the server over UDP, and **Reliable** communicates over TCP.
  {% endhint %}

## Reduce the total amount of P2P messaging in relay communication

You can use <mark style="color:orange;">Proud.CNetClient.GetPeerInfo</mark> to find out if the other clients you are calling RMI on are in direct P2P communication with you. If they were relay communicating, they could reduce the number of RMI calls they make to send their character's location from 8 times per second to 4 times per second.

## JIT(Just-in-time) P2P connections

ProudNet is designed to perform P2P hole punching only when required.

For example, even if you actually create a connection between two peers using <mark style="color:orange;">Proud.CNetServer.JoinP2PGroup()</mark>, the actual hole punching between the two peers is when a user initiates P2P messaging between them.

This has the effect of preventing NAT routers from being overwhelmed with port mapping entries.

If you want P2P hole punching to start as soon as a connection is established between two peers, you can select the value Always instead of JIT in <mark style="color:orange;">Proud.CNetServer.SetDirectP2PStartCondition()</mark>.

## Perform routed multicast on the server to multiple clients

ProudNet leverages P2P functionality to enable effective multicast in MMO games.\ <mark style="color:orange;">Server-to-client routed multicast</mark> is a feature that relays communication from the client to the server using P2P functionality, which can be used to reduce traffic generated by the server.

<figure><img src="https://content.gitbook.com/content/Ceg6wWD81CFYby05yPX5/blobs/9coVX48x0hwWp5r7oDpT/routed_multicast.png" alt=""><figcaption><p>Server-to-client routed multicast</p></figcaption></figure>

The following conditions must be met to enable <mark style="color:orange;">server-to-client routed multicast</mark>.

> * It must be [**Unreliable Messaging**](https://docs.proudnet.com/proudnet.eng/proudnet-note/dictionary#unreliable-messaging).
> * It must be a single call for [**multicast**](https://docs.proudnet.com/proudnet.eng/proudnet-note/dictionary#multicast).\
>   You cannot do <mark style="color:orange;">server-to-client routed multicast</mark> if you call RMI for each destination separately to send to multiple hosts.
> * Members of the parameters of <mark style="color:orange;">Proud.RmiContext</mark> <mark style="color:orange;">Proud.RmiContext.m\_unreliableS2CRoutedBroadcastMaxCount</mark> must be filled in.
> * If necessary, also fill in <mark style="color:orange;">Proud.RmiContext.m\_unreliableS2CRoutedBroadcastMaxPing</mark>. Default: default value
> * You must have previously communicated P2P or change the P2P connection condition from <mark style="color:orange;">JIT</mark> to <mark style="color:orange;">always</mark>.

## Including a server as a member of a P2P group

P2P groups can add servers as group members, which works well when you want messages sent to the P2P group to also be sent to the server.

Make sure your RMI stub is associated with the server side as well as the client.

For example, if you have a group of RMI functions called X, X::Proxy should be associated with <mark style="color:orange;">Proud.CNetClient.AttachProxy</mark>, and X::Stub should be associated with <mark style="color:orange;">Proud.CNetClient.AttachStub</mark> and <mark style="color:orange;">Proud.CNetServer.AttachStub</mark> so that the server can also receive RMI calls sent to the P2P group.\
After that, you need to set <mark style="color:orange;">Proud.CStartServerParameter.m\_allowServerAsP2PGroupMember</mark> to 'true' and start the server, so that the server is also allowed to be a member of the P2P group.<br>

When creating a P2P group or adding members to an existing P2P group, if you include <mark style="color:orange;">Proud.HostID\_Server</mark> as a parameter, the server will also be a member of the P2P group.

## Super Peer-focused P2P networking

One method of peer-to-peer communication in massively multiplayer online games (MO or casual) is for one member of the P2P group to be responsible for both sending and receiving messages for gameplay.\
This is sometimes referred to as <mark style="color:orange;">Super Peer</mark> <mark style="color:orange;">(or host)</mark> <mark style="color:orange;">driven</mark> <mark style="color:orange;">P2P networking</mark>.

In a <mark style="color:orange;">Super Peer-centric approach to P2P networking</mark>, while playing a game, each peer does not send messages directly to all members of the P2P group. Instead, they send messages to one designated Super Peer, who then sends them directly to all other members of the P2P group.

<figure><img src="https://content.gitbook.com/content/Ceg6wWD81CFYby05yPX5/blobs/ktewUtlWS4JrTTzXS5D6/super_peer.png" alt=""><figcaption><p>Super Peer example</p></figcaption></figure>

A client in a P2P group with a very good internet connection can effectively act as a super peer: traffic to the super peer client will take as much incoming traffic as the number of other clients, and as much outgoing traffic as the square of the number of other clients.

However, if none of the clients in a P2P group have good communication speeds, the quality of the game can suffer. Therefore, when implementing P2P networking focused on Super Peer, you should consider the communication quality of your Super Peer and choose it carefully.

### - How to choose a Super Peer

> * Peer on a direct internet line, not an internet router
> * Peer with high transmission rates
> * Peer with a high execution frame rate per second due to good performance

### - Execution performance and traffic considerations for Super Peer

One of the purposes of using a Super Peer is to have one of your clients perform computations that the server cannot handle. For physics engine computations and gameplay that is directly affected by the results of those computations, it makes sense to use a Super Peer to offload the processing.<br>

ProudNet uses the <mark style="color:orange;">frame rate</mark> to determine the execution performance of a Super Peer.\
To do this, we need to do the following.

> * Set <mark style="color:orange;">Proud.CSuperPeerSelectionPolicy.m\_frameRateWeight</mark> or use <mark style="color:orange;">Proud.CSuperPeerSelectionPolicy.GetOrdinary()</mark> during the Super Peer selection process.
> * &#x20;Pass the measured frame rate from your app to <mark style="color:orange;">Proud.CNetClient</mark> via <mark style="color:orange;">Proud.CNetClient.SetApplicationHint</mark>.

{% hint style="warning" %}
The transmission volume per second for home Internet typically does not exceed 30KB to 200KB and varies greatly.

Since Super Peer requires a significantly higher amount of transmissions per second than other peers, if it is selected as a computer under the home Internet, it is necessary to adjust the amount of communication, see [**throttling**](https://docs.proudnet.com/proudnet.eng/proudnet/communication-messages#auto-adjust-sending-volume-throttling).
{% endhint %}

***

## :arrow\_left: [**Back**](https://docs.proudnet.com/proudnet.eng/proudnet/using_pn/p2p)
