> For the complete documentation index, see [llms.txt](https://docs.proudnet.com/proudnet.cn/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.cn/proudnet/usage_pn.md).

# 活用 ProudNet

## ProudNet 伺服器

ProudNet 伺服器是 <mark style="color:orange;">Proud::CNetServer</mark> 實例，具有以下角色。\
另外，它還作爲P2P通信的relay服務器發揮着作用。

> * 接受並管理來自 ProudNet 用戶端的連接
> * 與客戶端進行通訊：RMI
> * 客戶端間P2P通訊的群組管理：參考[**P2P群組**](/proudnet.cn/proudnet/using_pn/p2p.md#p2p)

## ProudNet 客戶端

ProudNet 網路用戶端是 <mark style="color:orange;">Proud::CNetClient</mark> 實例，具有以下角色。

> * 與伺服器連線/中斷連線：請參閱[**從客戶端連線到伺服器**](/proudnet.cn/proudnet/using_pn/server_client.md#undefined-10)
> * 與伺服器通訊：RMI
> * 與其他客戶端的P2P通訊：RMI

<figure><img src="/files/yN06hgqknzEmx0EO9PHn" alt=""><figcaption><p>Client Server</p></figcaption></figure>

## ProudNet 協定類型

支援的訊息傳遞協定如下，您可以選擇一種並將其輸入為 RMI 函數呼叫中的參數。

<table><thead><tr><th width="217">協定類型</th><th>註釋</th></tr></thead><tbody><tr><td>Reliable messaging</td><td>雖然主機間收發信息的時間比unreliable長，但收發順序和到達是保證的。</td></tr><tr><td>Unreliable messaging</td><td>雖然主機間收發消息的時間比reliable短，但收發順序可能會不順，無法保證到達。</td></tr></tbody></table>

<mark style="color:orange;">Client</mark> 和 <mark style="color:orange;">Server</mark> 使用的通信協議

<table data-full-width="true"><thead><tr><th width="252">狀態</th><th width="283">Reliable P2P RMI</th><th width="191">Unreliable P2P RMI</th><th>Reliable C-S RMI</th><th>Unreliable C-S RMI</th></tr></thead><tbody><tr><td>正常</td><td>Reliable UDP</td><td>UDP</td><td>TCP</td><td>UDP</td></tr><tr><td>對等點之間的 UDP 通訊不良</td><td>Relay and Reliable UDP or TCP</td><td>Relay and TCP</td><td>TCP</td><td>UDP</td></tr><tr><td>雲端與伺服器之間的 UDP 通訊不良</td><td>Relay and TCP</td><td>Relay and TCP</td><td>TCP</td><td>TCP</td></tr></tbody></table>

{% hint style="info" %}

* <mark style="color:orange;">Reliable UDP</mark>是ProudNet自身實現功能。
* Relay由<mark style="color:orange;">Server</mark>負責。
  {% endhint %}

{% hint style="success" %}
**協議選擇技巧**\
第一次開發遊戲時，使用<mark style="color:orange;">Proud.RmiContext.ReliableSend</mark>將所有信息發送到<mark style="color:orange;">Reliable messaging</mark>。 然後參考訪問所有RMI呼叫時間，收集RMI消息收發明細。

一般來說,在遊戲程序中,20%以下的RMI信息種類佔全部收發量的80%以上,其中發送頻率非常高,即使發生20%以下的流失,也會找到沒有什麼問題的RMI,修改爲使用<mark style="color:orange;">Unreliable messaging</mark>。
{% endhint %}

## ProudNet客戶端-服務器通信

在ProudNet中，客戶端和服務器之間的通信以信息爲單位構成，每個信息對應1次RMI呼叫，reliable、unreliable通信均可進行。

{% hint style="success" %}
**參考**

[**RMI** ](/proudnet.cn/proudnet-note/dictionary.md#rmi)

[**伺服器-客戶端 通信** ](/proudnet.cn/proudnet-note/notes/client_server_communication.md)
{% endhint %}

## ProudNet P2P通訊效能

ProudNet擁有超越普遍化的打孔及接力技術的功能,非常強大,支持沒有連接等待時間的TCP等P2PReliable信息。\
由於對敏感或有缺陷的NAT裝置具有抗性,因此可以自行解決低速網絡超負荷的P2P發送量,用戶要求連接P2P通信(<mark style="color:orange;">Proud.CNetServerCreateP2PGroup</mark>或<mark style="color:orange;">Proud.CNetServer.JoinP2PGroup</mark>)後,立即執行客戶端之間的信息。

部分NAT設備因對同一內部地址的外部地址映射管理不當而丟失,ProudNet在客戶端之間設有不同的UDP socket,只在必要的情況下嘗試打孔,最大限度地減少這種映射信息的丟失。

例如，如果已連接P2P，但未進行真正的P2P通信，則不進行打孔。 因此,在調用<mark style="color:orange;">Proud.CNetServer.CreateP2PGroup</mark> , <mark style="color:orange;">Proud.CNetServer.JoinP2PGroup</mark>後,仍然調用<mark style="color:orange;">Proud.RmiContext.m\_relayed</mark>, <mark style="color:orange;">Proud.CNetClientInfo.m\_RelayedP2P</mark>, <mark style="color:orange;">Proud.CNetPeerInfo.m\_RelayedP2P</mark> 值是 false， 但一旦您開始使用 P2P 通信， 將會更改爲 true 。

即使在上傳速度比下載速度慢的家用電腦（例如ADSL或ADSL2+）上打孔，也可能無法克服傳輸量，且發送端的發送電腦或NAT裝置可能無法正常運作。

此時，ProudNet使用內建的解析功能來偵測多播客戶端的過度傳輸，並將多播分發到中繼伺服器。

「連接埠預測技術」稱為 NAT 打洞策略。\
該技術允許在symmetricNAT設備之間進行孔穿孔，但存在由於端口映射過多而產生的不良影響。\
為了最大限度地減少副作用，ProudNet 最初避免過度打孔，然後逐漸轉向連接埠預測等激進方法。 因此，在某些NAT設備中，將路由切換到直接P2P需要一段時間，但這不是問題，因為它先使用打洞，然後使用中繼技術。

{% hint style="success" %}
**參考**

[**打孔 (Hole Punching)**](/proudnet.cn/proudnet-note/dictionary.md#hole-punching)

[**P2P 通訊**](/proudnet.cn/proudnet/using_pn/p2p.md)
{% endhint %}

## ProudNet的UDP通訊相關效能

ProudNet在使用UDP協議時,爲了提高通信性能,採用<mark style="color:orange;">Coalesce</mark>, <mark style="color:orange;">MTU discovery fail</mark>預防等方法。

在小容量通訊（例如延遲小於 1 毫秒的 LAN 環境）中，通訊負載似乎大於實際 RMI 資料容量。 然而，在通訊量增加或延遲較高的 WAN 環境中，與 LAN 中的少量通訊相比，通訊負載會降低。

<figure><img src="/files/wqln1BBIXo7pjoSgaUUA" alt=""><figcaption><p>隨著RMI調用次數增加的通訊量關係</p></figcaption></figure>

在相距100公里以上的互聯網通信中，需要經過大量機型的Gateway設備的分組。\
每個網關都指定了不同的可承受MTU大小，但當發送方超過定義的MTU大小時，就會發生ICMP分組分組。

一些用戶由於害怕ICMP攻擊而設置屏蔽所有類型的ICMP分組,在這種情況下,由於無法處理ICMP分組分組,MTU discovery失敗,最終導致兩個主機之間的UDP通信中斷。

ProudNet 具有防止這種情況發生的功能。

## ProudNet 上的加密通信

ProudNet的加密通訊協定非常強大。

需要加密的訊息使用<mark style="color:orange;">對稱金鑰</mark>進行加密，此時使用的<mark style="color:orange;">對稱金鑰</mark>使用<mark style="color:orange;">公鑰</mark>進行加密並在主機之間進行交換。 這些加密金鑰無法被第三方破解，因為它們不僅在伺服器和用戶端中，而且在客戶端之間的 P2P 通訊中都被分配了唯一的值。

此外，加密訊息的內部內容每次傳輸到另一台主機時都會發生顯著變化，從而防止駭客在捕獲資料包後重新傳輸相同或相似訊息的嘗試。 但是，它的處理速度比非加密訊息傳遞要低，因此請謹慎使用。

ProudNet 使用 128 位元 RSA 作為非對稱金鑰演算法，使用 AES 或 Fast 作為<mark style="color:orange;">對稱金鑰</mark>演算法。 由於單獨使用RSA需要太多的計算量，因此將其與<mark style="color:orange;">對稱金鑰</mark>演算法結合使用。

它不僅為客戶端和伺服器之間的通訊提供了加密功能，還為P2P通訊提供了加密功能，提供了出色的安全性。 此外，RMI中使用的<mark style="color:orange;">對稱金鑰</mark>是高度可靠的，因為它是在初始伺服器連線時使用RSA演算法<mark style="color:orange;">公鑰</mark>加密後進行交換的。

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

&#x20;

{% hint style="danger" %}
ProudNet 用戶端連線到伺服器時發生的 <mark style="color:orange;">Proud::INetServerEvent::OnConnectionRequest</mark> 事件中的自訂欄位未加密。 請不要透過此方式傳遞您的訊息。
{% endhint %}

### - ProudNet加密技術

ProudNet 根據效能和安全性等級提供各種加密功能。\
若要傳送加密訊息，請呼叫 RMI 方法或在 <mark style="color:orange;">SendUserMessage</mark> 系列方法中輸入的參數中的 <mark style="color:orange;">Proud.RmiContext.m\_encryptMode</mark> 中選擇所需的加密方法。

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

```cpp
Proud::RmiContext rmiContext;
rmiContext.m_encryptMode = Proud::EncryptMode::EM_Secure;
// proxy 函數示例
Proxy.RequestLogon(Proud::HostID::HostID_Server, rmiContext, m_Name, password);
```

```cpp
Proud::RmiContext rmiContext;
rmiContext.m_encryptMode = Proud::EncryptMode::EM_Fast;
Proxy.RequestLogon(Proud::HostID::HostID_Server, rmiContext, m_Name, password);
```

或者您可以像這樣輕鬆地使用它。

```cpp
Proxy.RequestLogon(Proud::HostID::HostID_Server,Proud::RmiContext::SecureReliableSend, m_Name, password); 
// 使用 EM_Secure
```

```cpp
Proxy.RequestLogon(Proud::HostID::HostID_Server,Proud::RmiContext::FastEncryptedReliableSend, m_Name, password); 
// 使用 EM_Fast
```

{% endtab %}

{% tab title="C#" %}

<pre class="language-csharp"><code class="lang-csharp"><strong>Nettention.Proud.RmiContext rmiContext;
</strong>rmiContext.encryptMode = Nettention.Proud.EncryptMode.EM_Secure;
// proxy 函數示例
Proxy.RequestLogon(Nettention.Proud.HostID.HostID_Server, rmiContext, name, password);
</code></pre>

```csharp
Nettention.Proud.RmiContext rmiContext;
rmiContext.encryptMode = Nettention.Proud.EncryptMode.EM_Fast;
Proxy.RequestLogon(Nettention.Proud.HostID.HostID_Server, rmiContext, name, password);
```

```csharp
Proxy.RequestLogon(Nettention.Proud.HostID.HostID_Server,Nettention.Proud.RmiContext.SecureReliableSend, name, password); 
// 使用 EM_Secure
```

```csharp
Proxy.RequestLogon(Nettention.Proud.HostID.HostID_Server,Nettention.Proud.RmiContext.FastEncryptedReliableSend, name, password); 
// 使用 EM_Fast
```

{% endtab %}
{% endtabs %}

{% hint style="warning" %}
在P2P群組中使用加密功能時  <mark style="color:orange;">CStartServerParameterBase::m\_enableP2PEncryptedMessaging</mark> 的值必須設為 **true**。

在 C# 中，您可以使用 <mark style="color:orange;">StarSeverParameterBase.enableP2PEncryptedMessaging</mark>。
{% endhint %}

### - 加密金鑰長度：加密等級和效能之間的平衡

ProudNet 的加密過程涉及主機之間的內部金鑰交換。 此時，使用者可以設定交換和接收的金鑰長度，設定時必須考慮系統的效能和加密等級。<br>

加密金鑰的長度可以在啟動伺服器時在參數 <mark style="color:orange;">Proud.CStartServerParameter.m\_encryptedMessageKeyLength</mark> 和 <mark style="color:orange;">Proud.CStartServerParameter.m\_fastEncryptedMessageKeyLength</mark> 中設定。

> * <mark style="color:orange;">Proud.CStartServerParameter.m\_encryptedMessageKeyLength</mark> 參數
>
> 這是指使用 AES 加密時金鑰的長度，您可以設定 <mark style="color:orange;">Proud.EncryptLevel.EncryptLevel\_Low</mark>、<mark style="color:orange;">Proud.EncryptLevel.EncryptLevel\_Middle</mark> 和 <mark style="color:orange;">Proud.EncryptLevel.EncryptLevel\_High</mark> 的金鑰長度。
>
> &#x20;
>
> * <mark style="color:orange;">Proud.CStartServerParameter.m\_fastEncryptedMessageKeyLength</mark> 參數
>
> 指的是使用快速加密時的金鑰長度，可以設定<mark style="color:orange;">Proud.FastEncryptLevel.FastEncryptLevel\_Low</mark>、<mark style="color:orange;">Proud.FastEncryptLevel.FastEncryptLevel\_Middle</mark> 和 <mark style="color:orange;">Proud.FastEncryptLevel.FastEncryptLevel\_High</mark>的金鑰長度。

AES 加密比 Fast 稍慢，但提供高品質的加密。

然而，對於不重要的數據，例如角色移動訊息，或需要大量發送和接收的訊息，您可以使用Fast，因為它的效能很快。

### - ProudNet的Fast AES演算法性能比較

下面是ProudNet的Fast AES演算法的效能比較。 測量了執行 100,000 次加密和解密（每次一次）所需的時間。

<figure><img src="/files/k1Tw4Phlu6vmHW1TEqqC" alt=""><figcaption><p>ProudNet Fast AES演算法效能對比</p></figcaption></figure>

**測試規格**

<table><thead><tr><th width="175" align="center">項目</th><th>規格</th></tr></thead><tbody><tr><td align="center">OS</td><td>Windows 7 Professional K</td></tr><tr><td align="center">CPU</td><td>Intel(R) Core(TM) i7-3770 CPU @ 3.40GHz 3.40GHz</td></tr><tr><td align="center">RAM</td><td>16.0GB</td></tr><tr><td align="center">System type</td><td>64-bit Operating System</td></tr></tbody></table>

{% hint style="success" %}
**參考**

[**加密與解密**](/proudnet.cn/proudnet-note/notes/encryption_decoding.md)
{% endhint %}

## ProudNet 訊息壓縮功能

ProudNet允許對訊息進行壓縮和傳輸，並且透過使用主機的CPU來減少通訊量，從而提高效率。 若要壓縮訊息，請呼叫 RMI 方法或在呼叫 <mark style="color:orange;">SendUserMessage</mark> 方法時將參數 <mark style="color:orange;">Proud.RmiContext.m\_compressMode</mark> 設定為 <mark style="color:orange;">Proud.CM\_None</mark> 以外的值。

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

```cpp
Proud::RmiContext rmi = Proud::RmiContext::ReliableSend;
rmi.m_compressMode = Proud::CompressMode::CM_Zip;
 
Proxy.SendFileChunk(Proud::HostID::HostID_Server, rmi, dataBlock);
```

{% endtab %}

{% tab title="C#" %}

```csharp
Nettention.Proud.RmiContext rmi = Nettention.Proud.RmiContext.ReliableSend;
rmi.compressMode = Nettention.Proud.CompressMode.CM_Zip;
 
Proxy.SendFileChunk(Nettention.Proud.HostID.HostID_Server, rmi, dataBlock);
```

{% endtab %}
{% endtabs %}
