# Technical Notes

## Communicating with a separate UDP socket without ProudNet

Although it is not recommended, it provides an opportunity to use only ProudNet's [**hole punching**](/proudnet.eng/proudnet-note/dictionary.md#hole-punching) function while mixing 3rd party network engines.

This allows ProudNet to obtain completed hole punching information from client/server or P2P and communicate it on a UDP socket prepared separately from ProudNet.

Since the hole punching information obtained from ProudNet is the router's mapping of the <mark style="color:orange;">Client</mark>'s UDP socket, this UDP socket must be turned off. To do this, call <mark style="color:orange;">Proud.CNetClient.Disconnect</mark> or destroy the <mark style="color:orange;">Client</mark> object. The <mark style="color:orange;">Client</mark>'s UDP socket address is then reused by a 3rd party.

If you create duplicate UDP sockets without this process, both ProudNet and 3rd party UDP sockets will behave abnormally.

The main steps are outlined below.

> 1. First, we use <mark style="color:orange;">Proud.CNetClient.GetDirectP2PInfo</mark> to get the hole-punched information.<br>
> 2. Release the UDP socket occupied by ProudNet.\ <mark style="color:orange;">Proud.CNetClient.InvalidateUdpSocket</mark> closes the UDP socket that the <mark style="color:orange;">client</mark> has, leaving the router's hole-punching state intact. The value returned by <mark style="color:orange;">Proud.CNetClient.InvalidateUdpSocket</mark> can be utilized for peer-to-peer communication in a separate module.<br>
> 3. After calling <mark style="color:orange;">Proud.CNetClient.InvalidateUdpSocket</mark>, write <mark style="color:orange;">Proud.CNetClient.RestoreUdpSocket</mark> to create a new UDP socket to resume UDP communication between the server and the peer.<br>
> 4. Even if some routers are hole-punched, the hole-punching mapping may randomly change or evaporate after tens of seconds to several minutes. ProudNet solves this problem itself with its own relay fallback function. However, when using a 3rd party UDP socket, this problem must be resolved directly by the developer or 3rd party engine, otherwise P2P communication may fail.

<table><thead><tr><th>C++ function</th><th width="246">C# function</th><th>Description</th></tr></thead><tbody><tr><td>Proud.CNetClient.GetDirectP2PInfo</td><td>Nettention.Proud.NetClient.GetDirectP2PInfo</td><td>Get hole-punched information to communicate with other peers.</td></tr><tr><td>Proud.CNetClient.InvalidateUdpSocket</td><td>Nettention.Proud.NativeNetClient.InvalidateUdpSocket</td><td>After terminating the internal UDP socket, P2P communication with the server is forcibly switched to the bypass state.</td></tr><tr><td>Proud.CNetClient.RestoreUdpSocket</td><td>Nettention.Proud.NativeNetClient.RestoreUdpSocket</td><td>Recreate the removed UDP socket and resume punching UDP holes with the other peer.</td></tr><tr><td>Proud.CNetClient.Disconnect</td><td>Nettention.Proud.NetClient.Disconnect</td><td>Terminate the connection with the server and leave all P2P groups.</td></tr></tbody></table>

{% hint style="danger" %}
The above method is not normal usage.\
Therefore, ProudNet is not responsible for any problems caused by <mark style="color:orange;">use\_alternative\_p2p</mark>.
{% endhint %}

## Using ProudNet in a DLL project

If you want to use ProudNet as a static library but in a DLL project, you must call <mark style="color:orange;">Proud.Thread.NotifyDllProcessDetached</mark> in the <mark style="color:orange;">process detach case</mark> of the <mark style="color:orange;">DllMain</mark> function, otherwise you may experience freezing on program exit.

```cpp
BOOL APIENTRY DllMain( HMODULE hModule, DWORD  ul_reason_for_call, LPVOID lpReserved)
{
    switch (ul_reason_for_call)
    {
    case DLL_PROCESS_ATTACH:
    case DLL_THREAD_ATTACH:
    case DLL_THREAD_DETACH:
    break;
    case DLL_PROCESS_DETACH:
    {
        Thread::NotifyDllProcessDetached();
    }
    break;
    }
    return TRUE;
}
```

## Attaching ProudNet to a web server-based game server

<mark style="color:orange;">Web application server (WAS)</mark> are used to easily develop game servers, but they have the disadvantage of not being able to handle real-time multiplayer quickly, or the load on the server is too heavy for the server to handle gameplay.

To compensate, you can use a mix of WAS with a socket server like ProudNet.

### (1) Share data with each other by placing a database between the socket server and WAS

Although it is intuitive and simple, it has the disadvantage of increasing the processing load on the database, processing more than data sharing, and making it impossible to send requests to the socket server and receive responses from WAS.

<figure><img src="/files/TnboEPm3wnrfblWGndz9" alt=""><figcaption></figcaption></figure>

### (2) Socket server is equipped with the ability to process HTTP request responses, and WAS sends requests to the socket server in HTTP.

There are ways to do this, such as using the Microsoft REST SDK to write to a socket server.

<figure><img src="/files/Nqynuf0snVVAWJh10Ut3" alt=""><figcaption></figcaption></figure>

### (3) Use non-HTTP socket communication between WAS and a socket server

The WAS sends commands to the plugin, and the plugin takes those commands and sends them to the socket server. For ProudNet, you can use <mark style="color:orange;">NetClient</mark> or <mark style="color:orange;">LanClient</mark>.

#### How to program plugins in WAS

> <mark style="color:orange;">PHP</mark>: CGI or FastCGI\ <mark style="color:orange;">ASP.NET</mark>: C# class library\ <mark style="color:orange;">node.js</mark>: C plugin\ <mark style="color:orange;">Java</mark>: JNI

## Creating a bad network environment

It imitates a bad network environment by blocking UDP communications. \
You can temporarily or permanently stop UDP communication by calling <mark style="color:orange;">Proud.CNetClient.TEST\_FallbackUdpToTcp</mark>.

## TCP delayed sending and the Nagle algorithm

TCP has a built-in delayed sending feature that allows it to remain efficient when communicating on the WAN Internet, but it sends the data that needs to be sent to the other party with a slight delay.

The delayed transmission feature is sometimes referred to as the <mark style="color:orange;">Nagle algorithm</mark>. The <mark style="color:orange;">Nagle algorithm</mark> delays sending by 0.01 to 0.7 seconds, which can be unsuitable for online games, so ProudNet provides the ability to turn it off. When <mark style="color:orange;">Nagle algorithm</mark> is turned off, Delayed Send will be at most 0.01 seconds to prevent <mark style="color:orange;">Silly Window Syndrome</mark>.

For information on how to control the <mark style="color:orange;">Nagle algorithm</mark>, please see below.

<table data-full-width="false"><thead><tr><th width="275">C++ function</th><th>Description</th></tr></thead><tbody><tr><td>Proud.CStartServerParameter.m_enableNagleAlgorithm</td><td>Enable or disable the TCP delayed delivery feature and the Nagle algorithm feature.</td></tr><tr><td>Proud.CStartLanServerParameter.m_enableNagleAlgorithm</td><td>-</td></tr></tbody></table>

## Bypassing Apple's IPv6 policy

Due to Apple's policy, you cannot use addresses in the following formats when connecting to the server.

```
11.22.33.44
1122:3344:5566:7788:1122:3344:5566:7788
```

Instead, you must write the hostname in FQDN format.

```
myserver1.mygame.com
```

If you need to respond to Apple's policy quickly but you do not have the time to assign FQDN names for all your servers right away, you can use the bypassing solution provided by ProudNet.

In addition to the server address you want to connect to, you can enter different FQDNs in \[1] and \[2] as follows.

```cpp
CNetClient* nc = CNetClient::Create();
p.m_serverIP = "11.22.33.44";
p.m_publicDomainName1 = "www.nettention.com"; // [1]
p.m_publicDomainName2 = "www.nts.go.kr";  // [2]
nc->Connect(p);
```

{% hint style="warning" %}
**Caution**

* \[1] and \[2] must be different domains.
* \[1] and \[2] must not have IPv6 addresses.
* <mark style="color:orange;">NetClient</mark> never actually connects to the servers at \[1] and \[2], but \[1] and \[2] must be valid hosts.
  {% endhint %}

{% hint style="danger" %}
This bypassing is not a fundamental solution and does not guarantee normal access to all <mark style="color:orange;">NetServers</mark>. To fundamentally solve this problem, you must use the host name in FQDN format as recommended by Apple.
{% endhint %}

{% hint style="success" %}
**Reference**

&#x20;[**End IPv4 allocation**](https://namu.wiki/w/IP#s-2.1.2)
{% endhint %}

## Unicode-to-Multibyte Interconversion

Because ProudNet uses <mark style="color:orange;">Unicode</mark>, we recommend that you use Unicode in your development, but you can use ProudNet even if your program does not use Unicode.

If Unicode cannot be used (e.g., if the existing program is not already Unicode-based), the string input to ProudNet must be converted to Unicode and the output string must be converted to the multibyte code <mark style="color:orange;">MBCS</mark>.

The classes that play this role are <mark style="color:orange;">Proud::StringA2W</mark>, <mark style="color:orange;">Proud::StringW2A</mark>.

The <mark style="color:orange;">Proud::StringA2W</mark> class is responsible for converting <mark style="color:orange;">MBCS</mark> to Unicode, while <mark style="color:orange;">Proud::StringW2A</mark> converts Unicode to <mark style="color:orange;">MBCS</mark> and vice versa.

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

```cpp
void Foo()
{
    // Unicode to MBCS conversion
    Proud::String a=L"ABC";
    const char* b = Proud::StringW2A(a);
    
    // MBCS to Unicode conversion
    Proud::String c = Proud::StringA2W(b);
}
```

{% endtab %}
{% endtabs %}


---

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