# Communication messages

## Sending messages

When RMI Foo(int a,float b) is declared, if an RMI proxy is registered with the <mark style="color:orange;">Client</mark> or <mark style="color:orange;">Server</mark>, the proxy's RMI can be called to send a message. The messaging protocol can use either <mark style="color:orange;">ReliableSend</mark> or <mark style="color:orange;">UnreliableSend</mark> of the <mark style="color:orange;">RmiContext</mark>. Both client-to-server and peer-to-peer communication are available.<br>

Below is an example of sending a message.

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

```cpp
Proud::HostID oneHostID = ...; // 1 sending destination
int manyHostIDListCount = ...;
 
// Send RMI to the server.
myProxy.Foo(Proud::HostID_Server, Proud::RmiContext::ReliableSend, 3, 4);
 
// Send RMI to 1 sending destination.
myProxy.Foo(oneHostID, Proud::RmiContext::UeliableSend, 3, 4);
```

The destination can be the client's Host ID, the server's Host ID (<mark style="color:orange;">Proud::HostID\_Server</mark>), or yourself, and if you include a P2P group ID, it will be multicast to that P2P group.\
You can also multicast to multiple destinations at once. The first parameter is a pointer to an array of HostIDs instead of HostIDs and the size of the array of HostIDs.

```cpp
// Array of sending destinations
Proud::HostID sendTo[2];
sendTo[0] = ...;
sendTo[1] = ...;
 
// Send to multiple recipients at once.
myProxy.Foo(sendTo, 2, Proud::RmiContext::ReliableSend, 3, 4);
```

If there are duplicate destinations in the list, they will only be sent once instead of twice, and the list can contain not only one host but also P2P groups.
{% endtab %}

{% tab title="C#" %}

<pre class="language-csharp"><code class="lang-csharp"><strong>Nettetion.Proud.HostID oneHostID = ...; // 1 sending destination
</strong>int manyHostIDListCount = ...;

// Send RMI to the server.
myProxy.Foo(Nettention.Proud.HostID.HostID_Server, Nettention.Proud.RmiContext.ReliableSend, 3, 4);

// Send RMI to 1 sending destination.
myProxy.Foo(oneHostID, Nettention.Proud.RmiContext.UnreliableSend, 3, 4);
</code></pre>

The destination can be the client's Host ID, the server's Host ID (<mark style="color:orange;">Nettention.Proud.HostID.HostID\_Server</mark>), or yourself, and if you add a P2P group ID, it will be multicast to that P2P group.\
You can also multicast to multiple destinations at once. You can do this by putting an array of HostIDs instead of HostIDs as the first parameter.

```csharp
// Array of sending destinations
HostID[] sendTo = new HostID[2];
sendTo[0] = ...;
sendTo[1] = ...;

// Send to multiple recipients at once.
myProxy.Foo(sendTo, Nettention.Proud.RmiContext.ReliableSend, 3, 4);
```

{% endtab %}
{% endtabs %}

## Communication message size limits

ProudNet has a flexible size limit for communication messages, which is intended to prevent hacked clients from sending false signals to the server that they are unintentionally sending large messages.

For this reason, it is not recommended that game clients and servers communicate with each other to send and receive messages that are larger than about 64 KB.

The initial value for the maximum size of messages that can be sent and received is approximately 64 KB.\
However, server-to-server communication is immune to these hacking issues, server-to-server communication lines are lightning fast, and you will probably need to send and receive very large messages from time to time, which is why you might want to control the maximum size of messages in server-to-server communication.

This can be controlled via <mark style="color:orange;">SetMessageMaxLength</mark>. If a client attempts to send a message larger than the specified size, an exception will be thrown at the corresponding sending point on the client end.

| C++                                  | C#                                             |
| ------------------------------------ | ---------------------------------------------- |
| Proud.CNetServer.SetMessageMaxLength | Nettention.Proud.NetServer.SetMessageMaxLength |

<br>

## Auto-adjust sending volume (Throttling)

ProudNet features <mark style="color:orange;">throttling</mark> which allows for less communication failure even in low-speed environments, and enables high-quality networking in high-speed environments.

### - Message sending priority features

ProudNet provides a message sending priority feature.

If there are messages waiting in the egress buffer that have not yet been sent to the network line, priority 2 messages will be sent only after priority 1 messages have been fully sent.\
Similarly, messages at priority 3 will only start to be sent after messages at priority 2 are fully sent.

### - Utilizing the message sending priority features

* **Voice Chat**

Voice chat requires a large amount of messaging. Because the volume of voice chat communication can interfere with gameplay, it is recommended that messages related to gameplay be given a higher priority and voice chat a lower priority.<br>

* **Download real-time content for games**

You can develop games that require a quick install and then download the media data needed to start the game during gameplay. You can improve performance by giving higher priority to messages related to gameplay and lower priority to messages related to downloaded data.<br>

* **Bulk character position synchronisation**

Location synchronisation with characters that directly interact with the player character is more important than with other characters that do not interact directly, so sending the location of characters that are in combat with the player character or close to the camera at a higher priority and other messages at a lower priority can provide a better gaming experience.

When you call RMI, the input parameter <mark style="color:orange;">RmiContext</mark> has a member variable <mark style="color:orange;">priority</mark>. You can enter the message sending priority in this variable. The message sending priority is one of the values of <mark style="color:orange;">Proud.MessagePriority</mark>.

<mark style="color:orange;">Proud.RmiContext.ReliableSend</mark> and <mark style="color:orange;">Proud.RmiContext.UnreliableSend</mark> are global variables. Do not modify their priorities directly; create separate <mark style="color:orange;">RmiContext</mark> objects to use them.

### - Sending only the final message

Sending final message only is a feature that sends duplicate messages, such as messages that have accumulated in the send queue but have not been sent, but only sends the final message you want to send and cancels the rest of the accumulated messages.&#x20;

This is useful if you are playing an online game and want to send your character's location to another host.

<figure><img src="/files/cx2UpZAUdBQVfnzkD1UC" alt=""><figcaption><p>Feature of sending only final messages</p></figcaption></figure>

When the time 'Time' is 1, the character position (Pos) has already been sent to the communication line.\
And if the character's position at Time 2 and 3 has not been sent yet and is stored in the host's memory, and you want to send the latest position at Time 4, you do not need to send the character's position at Time 2 and 3, which are still waiting, so it is better to send the position at Time 4 without sending it.

#### How to use

You can do this by specifying a non-zero value for the member variable <mark style="color:orange;">uniqueID</mark> of the parameter <mark style="color:orange;">RmiContext</mark> that is passed in when calling RMI.\
If there is a message with the same <mark style="color:orange;">uniqueID</mark> before this message is queued by the RMI call, the old message will be removed and replaced with the new message.

{% hint style="warning" %}
Because <mark style="color:orange;">UnreliableSend</mark> is used in so many places, it is recommended that you create a separate <mark style="color:orange;">RmiContext</mark> object and give it a <mark style="color:orange;">uniqueID</mark> rather than using it directly.
{% endhint %}

#### Example usage

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

```cpp
// Proud.RmiContext.m_uniqueID Example usage
// Get a copy of the RmiContext object for the default unreliable send.
Proud::RmiContext rmi = Proud::RmiContext::UnreliableSend;
 
// In m_uniqueID, put the identifier of the character controlled by the localhost.
rmi.m_uniqueID = MyPlayerPetID;
 
// Send a message via RMI.
C2CProxy.MyRmiFunction(PeerHostID, rmi, blahblah);
```

{% endtab %}

{% tab title="C#" %}

```csharp
// Proud.RmiContext.m_uniqueID Example usage
// Get a copy of the RmiContext object for the default unreliable send.
Nettention.Proud.RmiContext rmi = Nettention.Proud.RmiContext.UnreliableSend;
 
// In uniqueID, put the identifier of the character controlled by the localhost.
rmi.uniqueID = MyPlayerPetID;
 
// Send a message via RMI.
C2CProxy.MyRmiFunction(PeerHostID, rmi, blahblah);
```

{% endtab %}
{% endtabs %}

## Detecting oversending

### - Detect oversending on each host

ProudNet has a <mark style="color:orange;">send queue</mark> internally. \
A send queue is "data to be sent" that waits in memory until the transmission is complete, when the amount of data you want to send is greater than the transmission rate the network line can handle.

The more you send, the more your send queue will continue to grow, so it is a good idea to measure your send volume to prevent it.<br>

#### Send Queue Measurement Methods

<table data-full-width="false"><thead><tr><th width="191">C++</th><th width="240">C#</th><th>Description</th></tr></thead><tbody><tr><td>Proud.CNetServer.GetClientInfo</td><td>Nettention.Proud.NetServer.GetClientInfo</td><td>Get information about the one peer associated with this object.</td></tr><tr><td>Proud.CNetClient.GetPeerInfo</td><td>Nettention.Proud.NetClient.GetPeerInfo</td><td>Get information about the peer 1 associated with this object.</td></tr><tr><td>Proud.CNetPeerInfo.m_sendQueuedAmountInBytes</td><td>Nettention.Proud.NetPeerInfo.sendQueuedAmountInBytes</td><td><p>Total amount of pending messages to be sent to the peer (in bytes)</p><ul><li>When fetching from peer to server: total amount sent by the client</li><li>When fetching from a peer to a client: the total amount sent by the client (but excludes relayed messages)</li></ul></td></tr></tbody></table>

{% hint style="info" %}
When the sending volume is high, it can be mitigated by [**Throttling**](#auto-adjust-sending-volume-throttling).
{% endhint %}

### - Oversending detection for each RMI type

The event callback <mark style="color:orange;">Proud.IRmiProxy.NotifySendByProxy</mark> that occurs for each RMI call has a parameter <mark style="color:orange;">Proud.MessageSummary</mark> that allows you to measure the amount of RMI communication for each call.


---

# Agent Instructions: Querying This Documentation

If you need additional information that is not directly available in this page, you can query the documentation dynamically by asking a question.

Perform an HTTP GET request on the current page URL with the `ask` query parameter:

```
GET https://docs.proudnet.com/proudnet.eng/proudnet/using_pn/communication-messages.md?ask=<question>
```

The question should be specific, self-contained, and written in natural language.
The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
