# P2P 通訊

客戶端間通訊或<mark style="color:orange;">peer-to-peer網絡(以下簡稱 P2P 通訊)</mark>是指客戶端主機之間不經過伺服器的直接通訊。

該功能在以下情況下非常有用。

> * 當資料量太大而無法透過伺服器進行通訊時
> * 當客戶端地理位置相近但伺服器距離太遠時
> * 當您希望透過在客戶端之間直接聯網而不透過伺服器來降低延遲

\
在層間同步移動時，可以透過使用P2P功能來減少伺服器流量。 但另一方面，隨著P2P連線數量的增加，客戶端流量可能會變得過多，並且始終存在被駭客攻擊的風險，因此也必須在伺服器上檢查是否已確定攻擊等重要資料。

為了提高針對駭客攻擊的安全性，ProudNet 在伺服器上管理一切，包括 P2P 群組的建立和發布。

\
要建立P2P連接，必須先在伺服器上的客戶端之間建立P2P群組。 客戶端只能與屬於同一P2P組的客戶端進行P2P通訊。

當伺服器上形成客戶端之間的P2P群組時，客戶端首先透過伺服器進行P2P中繼通訊。 同時，客戶端之間的P2P打洞是在後台進行的。\
如果P2P孔穿孔成功，從那時起客戶端之間的通信將直接進行，而無需經由服務器。 這叫先打洞，後接力。\
\
憑藉這些功能，ProudNet 允許在 P2P 群組形成或更改後立即在客戶端之間發送和接收訊息，並且 ProudNet 應用程式在啟動遊戲室時不需要等待時間。 另外，在MMORPG遊戲中，可靠地進行頻繁的P2P連接和斷開，以利用P2P來同步可見區域中的角色位置。

如果在形成P2P組後就開始客戶端之間的通信，伺服器端流量會暫時增加幾秒鐘。

<figure><img src="/files/TI4WbBx2sJGv8ChQZJPd" alt=""><figcaption><p>啟動P2P通訊後的內部進度</p></figcaption></figure>

打洞客戶端之間的P2P通訊使用UDP和ProudNet自研的Reliable UDP進行，但P2P中繼是透過UDP或TCP進行的，直到打洞成功。 客戶端進行P2P通訊時所使用的UDP連接埠與連接伺服器時所使用的UDP連接埠相同。

一般來說，中繼通訊的延遲是P2P通訊的兩倍以上，特別是伺服器距離越遠，差距就越大。

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

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

## P2P 組

### - 開設 P2P 組

要在ProudNet上與其他客戶端進行P2P通信，必須先在伺服器上開啟一個P2P群組。 如果使用 <mark style="color:orange;">Proud.CNetServer.CreateP2PGroup</mark> 在伺服器上開啟 P2P 群組，則用戶端將收到作為 P2P 群組成員的用戶端的 HostID 的事件 <mark style="color:orange;">Proud.INetClientEvent.OnP2PMemberJoin</mark>。 用戶端收到並處理後，伺服器將收到 <mark style="color:orange;">Proud.INetServerEvent.OnP2PGroupJoinMemberAckComplete</mark>。

當客戶端偵測到伺服器上 P2P 群組中的所有變更後想要處理其他事情時，此事件有效。

<figure><img src="/files/0dQzWqfawLWiMWaLAa4L" alt=""><figcaption><p>開設 P2P 組</p></figcaption></figure>

### - 如何使用

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

1\. 透過呼叫伺服器上的<mark style="color:orange;">CreateP2PGroup</mark>函數來建立P2P組。\
2\. 用戶端透過 <mark style="color:orange;">INetClientEvent::OnP2PMemberJoin</mark> 收到 P2P 群組已建立的回呼。\
3\. 透過<mark style="color:orange;">OnP2PMemberJoin</mark>函數接收進入群組的客戶端和Member的HostID值。

<table data-full-width="true"><thead><tr><th width="287">功能</th><th width="126">回呼</th><th>C++ 函數</th><th>C# 函數</th></tr></thead><tbody><tr><td>新增成員到P2P群組</td><td>伺服器</td><td>CNetServer::JoinP2PGroup</td><td>Nettention.Proud.NetServer.JoinP2PGroup</td></tr><tr><td></td><td>客戶</td><td>INetClientEvent::OnP2PMemberJoin</td><td>Nettention.Proud.NetClient.P2PMemberJoinHandler</td></tr><tr><td>刪除 P2P 組中的新 member</td><td>伺服器</td><td>CNetServer::LeaveP2PGroup</td><td>Nettention.Proud.NetServer.LeaveP2PGroup</td></tr><tr><td></td><td>客戶</td><td>INetClientEvent::OnP2PMemberLeave</td><td>Nettention.Proud.NetClient.P2PMemberLeaveHandler</td></tr><tr><td>刪除P2P組</td><td>伺服器</td><td>CNetServer::DestroyP2PGroup</td><td>Nettention.Proud.NetServer.DestroyP2PGroup</td></tr><tr><td></td><td>客戶</td><td>INetClientEvent::LeaveP2PGroup</td><td>Nettention.Proud.NetClient.LeaveP2PGroup</td></tr></tbody></table>

### - 用法範例

**在遊戲期間查看群組處理和聊天**

<table><thead><tr><th width="239">函數</th><th>註釋</th></tr></thead><tbody><tr><td>CreateP2PGroup</td><td>客戶端連線、建立聊天群組</td></tr><tr><td>DestroyP2PGroup</td><td>當客戶端斷開連線並且聊天群組被刪除時</td></tr><tr><td>JoinP2PGroup</td><td>當另一個用戶進入視野時、當新用戶進入房間時</td></tr><tr><td>LeaveP2PGroup</td><td>當其他用戶消失或現有用戶離開房間時</td></tr></tbody></table>

***

## 活用

{% content-ref url="/pages/X8CfVHzjy2qUgXUBhbn3" %}
[如何使用P2P通訊](/proudnet.cn/proudnet/using_pn/p2p/using_p2p.md)
{% endcontent-ref %}


---

# 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.cn/proudnet/using_pn/p2p.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.
