# Client-Server Communication

When a client connects to a server, communication is first established over TCP.

In the meantime, if a successful UDP holepunch to the server occurs in the background, UDP communication is possible, but until then, both reliable, [**unreliable messaging**](/proudnet.eng/proudnet-note/dictionary.md#unreliable-messaging) is replaced by TCP. However, after a successful UDP holepunch, [**reliable messaging**](/proudnet.eng/proudnet-note/dictionary.md#reliable-messaging) is replaced by UDP.

Clients each have a TCP port and a UDP port, and the server has one TCP listening port and one or more UDP ports. Clients maintain a TCP connection to the server and select one of the server-side UDP ports, meaning that the server shares multiple UDP ports evenly among all connected clients.

For example, if 40,000 clients communicate with a server that has 20,000 open UDP ports, there will be two clients communicating for each UDP port on the server side.

## Registering and Using Proxy & Stub Communication Objects

To add communication to the server and client, we will create a Common project that will be used by both the server and client for convenience, and prepare a PIDL file.\
In the prepared PIDL file, define the protocol for sending communication from the server to the client.

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

```cpp
Global S2C 3000
{
   Chat(Proud::StringA txt);
}
```

Compiling the above PIDL file will create a **Proxy** and **Stub** object.

&#x20;

### How to Use Proxy Objects

First, include the Header wherever you want to use it.

```cpp
// Server: Server ▶ As a Client
// To make the call,
// the server uses the Proxy object to make the call.
// Declare in header file
// Since we assume we are creating a Common project, 
// we will include the generated files 
// from the folder in the Common project.
#include "../Common/S2C_proxy.h"
  
// Declare in a cpp file
#include "../Common/S2C_proxy.cpp"
```

&#x20;

Create a **proxy** and register it with the server object.

```cpp
// Creates an object.
S2C::Proxy g_S2CProxy;
  
void main()
{
    // The Server object you created 
    // in the Server description.
    CNetServer* srv = 
         ProudNet::CreateServer();
    Svr->AttachProxy(&g_S2CProxy);
  
    // Omitted below
}
```

We registered it by passing a pointer to the created **Proxy** object using a function called **AttachProxy**. \
**AttachProxy** can register multiple types of PIDLs by managing them internally as an array.\
Once registered, you can use the functions of the **Proxy** object to communicate.

```cpp
// The HostID and RmiContext
// are added automatically.
// Insert the HostID value of the Client 
// you want to send as hostID.
g_S2CProxy.Chat(
         hostID, 
         RmiContext::ReliableSend, 
         “Send Message”);
```

&#x20;

Like **proxy**, **stub** includes a header wherever you want to use it.

```cpp
Client:
 Server ▶ Since it is a client, the client
 includes a stub object to receive calls.
// Declare in header file 
// Since we assumed
// we were creating a Common project, 
// we would include the file created in the Common folder.
#include "../Common/S2C_stub.h"
  
// Declare in a CPP file
#include "../Common/S2C_stub.cpp"
```

In the case of the **Stub** object, you must create and use an inherited object because it is a defining function of the protocol to be received.\
If you register it using the **AttachStub** function, it will be called when that call comes in.\
Inside the generated **Stub** object, a Define is created, which allows you to avoid having to modify your cpp and h files separately when you change protocols.

```cpp
#define DECRMI_C2S_Chat bool Chat(
        Proud::HostID remote,
        Proud::RmiContext &rmiContext,
        const Proud::StringA txt)
```

Among the define statements specified in the **Stub Class**, declare <mark style="color:orange;">DEFRMI\_NameSpace\_function name</mark> in the header file of the inherited object and <mark style="color:orange;">DECRMI\_NameSpace\_function name (Class\_Name)</mark> in the cpp.

```cpp
class CS2CStub : public S2C::Stub
{
public:
  
// The protocol is handled
// as a define statement in the stub 
// so that the user does not have to modify the class if it changes.
// If it is 'DEFRMI_NameSpace_FunctionName',
// declare it in the header.
    DECRMI_S2C_Chat;
};
CS2CStub g_S2CStub;
  
// ‘DEFRMI_Protocol Taxonomy name_protocol name(
//               Inherited class name)’
// then declare it in the CPP.
DEFRMI_S2C_Chat(CS2CStub)
{
    printf( 
         "[Client] HostID:%d, text: %s”, 
         remote, 
         txt);
  
         // It must return true
    return true;
}
```

Returning 'True' means that it has been processed.\
If it returns 'False', the <mark style="color:orange;">OnNoRmiProcessed Event</mark> is called because the user has not processed the protocol.\
Of the function arguments called with <mark style="color:orange;">DEFRMI\_S2C\_Chat</mark>, remote is the value of the HostID of the other party that called the RMI.\
By invoking the **Proxy** with this ID value, you can send communication to the desired party.

&#x20;

Now we will register the **Stub** object we created with the Client object.

```cpp
CNetClient *client 
         = ProudNet:CreateClient();
client->AttachStub(&g_S2CStub);
// Omitted below
```

The **AttachStub** function is also managed internally as an array, and is registered by passing a pointer to it.
{% endtab %}

{% tab title="C#" %}

### How to Use Proxy Objects

Create classes like Proxy, Stub, etc. that are included in the PIDL compilation output.

```csharp
CommonC2C.Proxy c2cProxy = new CommonC2C.Proxy();
CommonC2S.Proxy c2sProxy = new CommonC2S.Proxy();
```

Create proxies and **attach** them to clients.

```csharp
Nettention.Proud.NetClient netClient = new Nettention.Proud.NetClient();
netClient.AttachProxy(c2cProxy);
netClient.AttachProxy(c2sProxy);
```

### How to Use Stub Objects

```csharp
CommonS2C.Stub s2cStub = new CommonS2C.Stub();
CommonC2C.Stub c2cStub = new CommonC2C.Stub();
```

Like **Proxy**, you create **stub** where you want to use them and **attach** them to the Client.

Unlike the C++ version, the DotNet version has the stub as a delegate.

<pre class="language-csharp"><code class="lang-csharp">// Set the delegate to handle the stub.
s2cStub.NotifyLocalHeroViewersGroupID = NotifyLocalHeroViewersGroupID; //&#x3C;- Set up the functions below.

//Similarly, create and set up the functions below.
s2cStub.RemoteHero_Appear = RemoteHero_Appear;

<strong>s2cStub.RemoteHero_Disappear = RemoteHero_Disappear;
</strong>
c2cStub.P2P_LocalHero_Move = P2P_LocalHero_Move;


...

netClient.AttachStub(s2cStub);

netClient.AttachStub(c2cStub);

...


//Create a function for the delegate.
bool NotifyLocalHeroViewersGroupID(Nettention.Proud.HostID remote, Nettention.Proud.RmiContext rmiContext, Nettention.Proud.HostID localHeroViewersGroupID)
{
    ...
    return true;
}

</code></pre>

\
Initialize Nettention.Proud.NetConnectionParam, call Nettention.Proud.NetClient.Connect() on and connects to the server.

```cpp
Nettention.Proud.NetConnectionParam param = new Nettention.Proud.NetConnectionParam();

//Match the protocolVersion.
param.protocolVersion.Set(new System.Guid("{0x7b7e9c20,0x309c,0x4364,{0xb4,0x9c,0xc6,0xc,0xcd,0x25,0xaf,0xa0}}"));

//Set the port to connect to.
param.serverPort = 32222;

//Set the IP address to connect to.
param.serverIP = serverAddr;

netClient.Connect(param);
```

{% endtab %}
{% endtabs %}

{% hint style="info" %}
Be sure to check your traffic after development.\
Traffic requires checking the amount of communication on each client, server (and Super Peer if you use Super Peer), etc. and removing unnecessary traffic.\
\
To check your traffic, you can use the methods below.<br>

* Use a tool like <mark style="color:orange;">NetLimiter</mark>.
* There is a way to run exactly as many processes as you want to use on one computer, and then check the number of bytes sent and received per interval in the Task Manager.
* You can use ProudNet's internal function <mark style="color:orange;">CNetServer::GetStats(CNetServerStats \&outVal);</mark> to get real-time traffic sent and received per second, the number sent or received, and more.\
  If the total traffic from a single client is roughly 20-30 KB or more, you may experience issues with your international service.
  {% endhint %}

{% hint style="danger" %}
Tools like <mark style="color:orange;">NetLimiter</mark> are recommended to be deleted after use.\ <mark style="color:orange;">Kernel Hooking</mark> puts 20x the original speed burden on the core holding the communication daubers.
{% endhint %}

## Event

### - Common to client and server

Using <mark style="color:orange;">errorInfo</mark> -> <mark style="color:orange;">ToString();</mark> in the parameter <mark style="color:orange;">errorInfo</mark>, you can easily get information about the problem.

<table><thead><tr><th width="203">Event</th><th>Description</th></tr></thead><tbody><tr><td>OnError</td><td>Callbacks for information about errors or usage issues that occur inside ProudNet.</td></tr><tr><td>OnWarnning</td><td>Call back information that is not critical but potentially problematic.</td></tr><tr><td>OnInformation</td><td>Callbacks for information about internal context and tracking, etc.</td></tr><tr><td>OnException</td><td>Call internal Exception error information.</td></tr><tr><td>OnNoRmiProcessed</td><td>Declared in the PIDL, but called when the Event is not inherited from the Stub, or when the user returns false.</td></tr></tbody></table>

### - Server

This can be used for performance testing and more.

<table><thead><tr><th width="261">Event</th><th>Description</th></tr></thead><tbody><tr><td>OnUserWorkerThreadBegin</td><td>Called when a Thread in the User Worker Thread Pool is started.</td></tr><tr><td>OnUserWorkerThreadEnd</td><td>Called at the end of a thread in the User Worker Thread Pool.</td></tr></tbody></table>


---

# 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-note/notes/client_server_communication.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.
