> For the complete documentation index, see [llms.txt](https://docs.proudnet.com/proudnet.eng/llms.txt). Markdown versions of documentation pages are available by appending `.md` to page URLs; this page is available as [Markdown](https://docs.proudnet.com/proudnet.eng/proudnet-note/sample.md).

# Sample examples

The examples below are based on the <mark style="color:orange;">git sample project</mark>, see the link below for more information.

:open\_file\_folder: [**Download C++ examples**](https://github.com/Nettention/ProudNet_Sample/tree/main/Simple)&#x20;

:open\_file\_folder: [**Download C# examples**](https://github.com/Nettention/ProudNet_Sample/tree/main/SimpleCSharp)

## Client

### - Proxy & Stub

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

<pre class="language-cpp"><code class="lang-cpp"><strong>// Client -> Server RMI Proxy instance
</strong><strong>Simple::Proxy g_SimpleProxy;
</strong>
// Unlike an RMI proxy, it is used after overriding a function.
class SimpleStub : public Simple::Stub
{
public:
	DECRMI_Simple_ShowChat;
	DECRMI_Simple_SystemChat;

	DECRMI_Simple_P2PChat;
};

// RMI stub instance for receiving messages
SimpleStub g_SimpleStub;
</code></pre>

{% endtab %}

{% tab title="C#" %}

```csharp
using namespace Nettention.Proud;

// An RMI proxy is used to send messages.
// The function call is executed in a different process.
static Simple.Proxy g_Proxy = new Simple.Proxy();

// The RMI stub is used to receive messages.
static Simple.Stub g_Stub = new Simple.Stub();
```

{% endtab %}
{% endtabs %}

### - Defining RMI functions

{% tabs %}
{% tab title="C++" %}
RMI functions use the following conventions for easy naming.

\=> <mark style="color:orange;">DEFRMI\_GlobalName\_FunctionName</mark>

```cpp
DEFRMI_Simple_P2PChat(SimpleStub)
{
    ...

    // It has no special meaning, but must return true.
    return true;
}

DEFRMI_Simple_ShowChat(SimpleStub)
{
    ...
    return true;
}

DEFRMI_Simple_SystemChat(SimpleStub)
{
    ...
    return true;
}
```

{% endtab %}

{% tab title="C#" %}

```csharp
// A function that defines what to do when each stub function is received.
g_Stub.P2PChat = (...) =>
{
    ...
    return true;
}
    
g_Stub.ShowChat = (...) =>
{
    ...
    return true;
}
    
g_Stub.SystemChat = (...) =>
{
    ...
    return true;
}
```

{% endtab %}
{% endtabs %}

### - Create a NetClient object&#x20;

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

```cpp
std::shared_ptr<Proud::CNetClient> netClient(Proud::CNetClient::Create());
```

{% endtab %}

{% tab title="C#" %}

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

{% endtab %}
{% endtabs %}

### - Connecting Events&#x20;

{% tabs %}
{% tab title="C++" %}
\
You can design the logic you need in the server connection event and then use it.

```cpp
// Events that are called after the server connection is complete
netClient->OnJoinServerComplete = 
   [&](ErrorInfo *info, const ByteArray &replyFromServer)
{
    ...
}
    
// Events to run when the server is disconnected
netClient->OnLeaveServer = [&](ErrorInfo *errorInfo)
{
    ...
}
    
// Event to fire when a new p2p connection comes in
// memberHostID : p2p Connected Client ID
// groupHostID : p2p Connected Group ID
netClient->OnP2PMemberJoin = 
    [&](HostID memberHostID, HostID groupHostID,int memberCount, const ByteArray &customField)
{
    ...
}
    
// Events to fire when a p2p connection is lost 
netClient->OnP2PMemberLeave = 
    [](HostID memberHostID, HostID groupHostID,int memberCount)
{
    ...
}
```

{% endtab %}

{% tab title="C#" %}

```csharp
// Events that are called after the server connection is complete
netClient.JoinServerCompleteHandler = (info, replyFromServer) =>
{
    ...
};

// Logic to run when the server is disconnected
netClient.LeaveServerHandler = (errorInfo) =>
{
    ...
};

// Logic to run when a new member is added to a p2p group
netClient.P2PMemberJoinHandler = 
    (memberHostID, groupHostID, memberCount, customField) =>
{
    ...
};

// Logic to execute when a p2p member is disconnected
netClient.P2PMemberLeaveHandler = (memberHostID, groupHostID, memberCount) =>
{
    ...
};
```

{% endtab %}
{% endtabs %}

### - Proxy & Stub Registration

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

```cpp
// Register the proxy and stub you created with CNetClient
netClient->AttachProxy(&g_SimpleProxy);
netClient->AttachStub(&g_SimpleStub);
```

{% endtab %}

{% tab title="C#" %}

```csharp
// Connecting a proxy and stub to a NetClient instance
netClient.AttachProxy(g_Proxy);	    // Client-to-server => From client to server
netClient.AttachStub(g_Stub);	   // server-to-client => From server to client
```

{% endtab %}
{% endtabs %}

### - Connect to a server

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

```cpp
// Setting the parameters needed to start the server
Proud::CNetConnectionParam cp;

// You must enter the same protocol version as the server. You may not enter any at all.
cp.m_protocolVersion = g_Version;
cp.m_closeNoPingPongTcpConnections = false;
cp.m_serverPort = g_ServerPort;	

// Start connecting to the server
// This function returns immediately.
// In the meantime, it will try to connect in the background,
// the result is signaled by the OnJoinServerComplete event.
netClient->Connect(cp);
```

Then, in a function that will be called every frame, call <mark style="color:orange;">netClient</mark> -> <mark style="color:orange;">FrameMove()</mark>.

```cpp
// Example
while (true)
{
    netClient->FrameMove();
}
```

{% endtab %}

{% tab title="C#" %}

```csharp
// Setting the parameters needed to start the server
Nettention.Proud.NetConnectionParam cp = 
    new Nettention.Proud.NetConnectionParam();

// Same protocol version as the server
cp.protocolVersion.Set(SimpleCSharp.Vars.m_Version);

// server address
cp.serverIP = "localhost";

// server port
cp.serverPort = (ushort)SimpleCSharp.Vars.m_serverPort;

// Start connecting to the server
// This function returns immediately.
// In the meantime, it will try to connect in the background,
// the OnJoinServerComplete event indicates that the connection is complete.
netClient.Connect(cp);
```

Call <mark style="color:orange;">netClient.FrameMove()</mark> in a function that will be called every frame thereafter.

```csharp
// Example
while (true)
{
    netClient.FrameMove();
}
```

{% endtab %}
{% endtabs %}

{% hint style="warning" %}
By default, a <mark style="color:orange;">FrameMove</mark> must be performed before the event is fired.
{% endhint %}

## Server

### - Proxy & Stub

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

```cpp
// RMI Proxy for Server to Client Transfers
Simple::Proxy g_SimpleProxy;


// Unlike an RMI proxy, it is used after overriding a function.
class SimpleStub : public Simple::Stub
{
public:
	DECRMI_Simple_Chat;
};

// Server -> Client RMI Stub Instance
SimpleStub g_SimpleStub;
```

{% endtab %}

{% tab title="C#" %}

```csharp
using namespace Nettention.Proud;

// RMI Stub for receiving messages from clients
static Simple.Stub g_Stub = new Simple.Stub();

// RMI proxy
static Simple.Proxy g_Proxy = new Simple.Proxy();
```

{% endtab %}
{% endtabs %}

### - Defining RMI functions

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

<pre class="language-cpp"><code class="lang-cpp"><strong>DEFRMI_Simple_Chat(SimpleStub)
</strong>{
    ...
    return true;
}
</code></pre>

{% endtab %}

{% tab title="C#" %}

<pre class="language-csharp"><code class="lang-csharp">// Define logic to run when a client receives a chat message.
<strong>g_Stub.Chat = (...) =>
</strong>{
    ...
    return true;
};
</code></pre>

{% endtab %}
{% endtabs %}

### - Create a NetServer object

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

```cpp
std::shared_ptr<Proud::CNetServer> srv(Proud::CNetServer::Create());
```

{% endtab %}

{% tab title="C#" %}

```csharp
Nettention.Proud.NetServer srv = new Nettention.Proud.NetServer();
```

{% endtab %}
{% endtabs %}

### - Connecting Events

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

```cpp
// Sets the logic to run when a client connects to the server.
srv->OnClientJoin = 
    [](CNetClientInfo* clientInfo, ErrorInfo* errorInfo, const ByteArray& comment)
{
    ...
};

// Sets the logic to run when the client server connection is lost.
srv->OnClientLeave = 
    [](CNetClientInfo *clientInfo, ErrorInfo *errorInfo, const ByteArray& comment)
{
    ...
};
```

{% endtab %}

{% tab title="C#" %}

```csharp
// Sets the logic to run when a client connects to the server.
srv.ClientJoinHandler = (clientInfo) =>
{
    ...
};

// Sets the logic to run when the client server connection is lost.
srv.ClientLeaveHandler = (clientInfo, errorInfo, comment) =>
{
    ...
};
```

{% endtab %}
{% endtabs %}

### - Proxy & Stub Registration

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

```cpp
// Register the proxy and stub on the created CNetServer instance.
srv->AttachStub(&g_SimpleStub);
srv->AttachProxy(&g_SimpleProxy);
```

{% endtab %}

{% tab title="C#" %}

```csharp
// Register the proxy and stub on the created CNetServer instance.
srv.AttachStub(g_Stub);
srv.AttachProxy(g_Proxy);
```

{% endtab %}
{% endtabs %}

### Start a server

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

```cpp
Proud::CStartServerParameter p1;

// This must be the same to the client. => Must be the same as the client.
p1.m_protocolVersion = g_Version; 

// TCP listening endpoint => TCP connections incoming PORT
p1.m_tcpPorts.Add(g_ServerPort); 

/* Start the server
This function raises an exception on failure.
If you don't specifically specify a threading model, 
RMI functions and event callbacks by sending messages are invoked in a partitioned thread pool.
You can specify the thread model separately, which is covered in the help. https://guide.nettention.com/cpp_ko#thread_pool_sharing
*/
srv->Start(p1);
```

{% endtab %}

{% tab title="C#" %}

```csharp
var p1 = new Nettention.Proud.StartServerParameter();

// This must be the same to the client. => Must be the same as the client.
p1.protocolVersion = new Nettention.Proud.Guid(Vars.m_Version); 

// TCP listening endpoint => TCP connection incoming PORT
p1.tcpPorts.Add(Vars.m_serverPort);

/* Start the server
This function raises an exception on failure.
If you don't specifically specify a threading model, 
RMI functions and event callbacks by sending messages are invoked in a partitioned thread pool.
You can specify the thread model separately, which is covered in the help. https://guide.nettention.com/cpp_ko#thread_pool_sharing
*/
srv.Start(p1);
```

{% endtab %}
{% endtabs %}

## Common

### - vars.h

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

```cpp
extern Proud::Guid g_Version;
extern int g_ServerPort;
```

{% endtab %}
{% endtabs %}

### - vars.cpp, vars.cs

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

```cpp
// Defined protocol version
// Both the server and client must have the same value.
PNGUID guid = { 0x3ae33249, 0xecc6, 0x4980, { 0xbc, 0x5d, 0x7b, 0xa, 0x99, 0x9c, 0x7, 0x39 } };
Guid g_Version = Guid(guid);

// TCP listening port number.
int g_ServerPort = 33334;
```

{% endtab %}

{% tab title="C#" %}

```csharp
namespace SimpleCSharp
{
    public class Vars
    {
        // protocol version to apply equally to server and client
        public static System.Guid m_Version = new System.Guid("{ 0x3ae33249, 0xecc6, 0x4980, { 0xbc, 0x5d, 0x7b, 0xa, 0x99, 0x9c, 0x7, 0x39 } }");
        public static int m_serverPort = 33334;
    }
}
```

{% endtab %}
{% endtabs %}


---

# Agent Instructions
This documentation is published with GitBook. GitBook is the documentation platform designed so that both humans and AI agents can read, navigate, and reason over technical content effectively. Learn more at gitbook.com.

## 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/sample.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.
