> 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/using_pn/p2p.md).

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