# 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 %}
