> ## Documentation Index
> Fetch the complete documentation index at: https://devdocs.xbox.com/llms.txt
> Use this file to discover all available pages before exploring further.

# GDK 中的 Windows Sockets 簡介

> Microsoft Game Development Kit 中的 Windows Sockets 簡介

Microsoft Game Development Kit (GDK) 支援使用 [Windows Sockets 2 (Winsock)](https://learn.microsoft.com/windows/desktop/WinSock/windows-sockets-start-page-2) API。

Windows Sockets 2 (Winsock) 可讓您建立進階的網際網路、內部網路及其他具備網路功能的應用程式，以透過線路傳輸應用程式資料，而不受所使用的網路通訊協定影響。

Microsoft Game Development Kit (GDK) 遊戲與 Winsock 互動的方式，通常與 Win32 程式與 Winsock 互動的方式相同。

本主題說明在 Microsoft Game Development Kit (GDK) 遊戲中使用 Winsock 的細微差異和特定最佳做法。

## 設定

本節說明使用 Winsock API 時需要包含哪些 .h 和 .lib 檔案。

* 在您的原始程式檔中新增 `#include <winhttp.h>`。
* 對於 PC 遊戲，請繼續連結 `Winhttp.lib`。
* 對於 XBOX 主機遊戲，您必須連結 `XGamePlatform.lib`，而不是直接連結 `Winhttp.lib`。

只有 `WINAPI_PARTITION_GAMES` API 系列下的 API 可在 Microsoft Game Development Kit (GDK) 遊戲中運作。

## 網路初始化

在第一次呼叫 [WSAStartup](https://learn.microsoft.com/windows/desktop/api/winsock/nf-winsock-wsastartup) 之前，Microsoft Game Development Kit (GDK) 遊戲必須確保網路堆疊已就緒。如果在遊戲的啟動過程中過早呼叫 `WSAStartup`，`WSAStartup` 或後續的 Winsock 呼叫可能會失敗。如需如何判斷網路堆疊何時就緒的詳細資料，請參閱[網路初始化和連線能力](/zh-TW/build/console-features/networking/initialization-connectivity-networking)。

<a id="SuspendResume" />

## 暫停與繼續

您應該透過 `RegisterAppStateChangeNotification` 註冊暫停與繼續事件。暫停時，您應該關閉所有通訊端控制代碼並呼叫 [WSACleanup](https://learn.microsoft.com/windows/desktop/api/winsock/nf-winsock-wsacleanup)。繼續時，您應該再次等待[網路初始化](/zh-TW/build/console-features/networking/initialization-connectivity-networking)，然後再呼叫 [WSAStartup](https://learn.microsoft.com/windows/desktop/api/winsock/nf-winsock-wsastartup) 並建立任何新的通訊端。

<a id="ID4EQBAC" />

## Microsoft Game Development Kit (GDK) 慣用本機使用者資料包通訊協定 (UDP) 多人遊戲連接埠 API

Microsoft Game Development Kit (GDK) [慣用本機 UDP 多人遊戲連接埠](/zh-TW/build/console-features/networking/game-mesh/preferred-local-udp-multiplayer-port-networking) API 會傳回一個經過動態選取的最佳連接埠，遊戲應使用 Winsock [繫結](https://learn.microsoft.com/windows/desktop/api/winsock/nf-winsock-bind)至該連接埠，以透過 UDP 進行遊戲內通訊。Microsoft Game Development Kit (GDK) 平台會確保此特定連接埠最有可能適用於每位使用者的特定網路環境。使用此特定連接埠可最大化地利用平台的客戶支援和診斷流程、提升標準化網路位址轉譯 (NAT) 相容性、提供標準化的 UPnP™ 認證裝置功能，並將封包識別為對即時敏感的封包，以供服務品質 (QoS) 路由器和 ISP 演算法使用。

UDP 連接埠與依賴點對點網路拓撲的遊戲特別相關。它是唯一允許輸入 UDP 封包在不執行防火牆打洞的情況下通過防火牆的連接埠。在 Microsoft Game Development Kit (GDK) 中依賴點對點網路拓撲的遊戲，仍應自行提供公用 IP 位址和連接埠探索，以及為具有中等或嚴格 NAT 類型的用戶端提供 NAT 打洞解決方案。慣用連接埠本身可以提高這些技術的成功率，但無法取代它們。

使用用戶端/伺服器網路拓撲的遊戲也可受益於使用 UDP 連接埠。對於醫院、飯店和大學宿舍中常見的強制網路門戶及其他以來源為基礎的篩選方法，疑難排解、UPnP™ 和封包識別仍然相關。

我們強烈建議 Microsoft Game Development Kit (GDK) 遊戲將慣用本機 UDP 多人遊戲連接埠用於其主要的多人遊戲和聊天網路流量。

<a id="ID4EQBAD" />

## 通訊端的安全性

Microsoft Game Development Kit (GDK) 遊戲有責任確保透過 Winsock API 在網路上傳輸的所有資料，都具有適當的安全性和加密。

[BCrypt](https://learn.microsoft.com/windows/desktop/api/bcrypt/index)、[WinCrypt](https://learn.microsoft.com/windows/desktop/api/wincrypt/index)、[schannel](https://learn.microsoft.com/windows/desktop/api/schannel/index) 及其他標準 Windows API 提供建議的密碼編譯基本元素。Microsoft Game Development Kit (GDK) 遊戲應使用這些 API，針對所有通訊端流程實作資料包傳輸層安全性 (DTLS) 及其他標準化的安全性通訊協定。

對於不想實作自有安全性模型的遊戲，Microsoft Game Development Kit (GDK) 程式庫 [PlayFab Party](/zh-TW/build/console-features/networking/game-mesh/playfab-party-intro-networking) 除了其他功能之外，還提供完整且整合的通訊端安全性方案。

<a id="SocketMemory" />

## 通訊端記憶體考量

Microsoft Game Development Kit (GDK) 遊戲目前只有大約 16MB 可供網路堆疊用於所有 WinSock 和 WinHTTP 使用，超過此限制後系統可能會變得不穩定。記憶體消耗的最大來源之一是 WinSock 核心模式傳送和接收記憶體集區，輸入和輸出的封包會儲存在其中，直到能透過線路傳送，或透過眾多 `recv` 變體之一傳輸至遊戲的使用者模式記憶體為止。

特別是在高頻寬的情況下，您的遊戲有責任以低延遲將資料傳輸至自己的使用者模式緩衝區，且速率至少要等於遠端對等或伺服器推送資料的速率。有幾種方法可以做到這一點，其複雜度和保證程度逐漸提高，但以下所有建議的基本目標，都是一律讓使用者模式緩衝區處於擱置狀態，以便在資料到達時立即傳輸，讓核心不需要配置越來越多的記憶體。其最終效果是將擱置中未處理資料的記憶體使用量，從極為有限的核心集區，轉移到您在大得多的遊戲記憶體集區內直接管理的記憶體。

使用 WinSock 的較高層級 API 通常具有適當的機制，可控制其通訊端的核心記憶體使用量。[WinHTTP](/zh-TW/build/console-features/networking/web-requests/intro-winhttp) 和 [XCurl](/zh-TW/build/console-features/networking/web-requests/intro-xcurl) 都允許透過各自的讀取通知機制來控制其核心記憶體使用量，而 [XSAPI](https://learn.microsoft.com/windows/uwp/xbox-live/xsapi-flat-c) 和 [PlayFab Party](/zh-TW/build/console-features/networking/game-mesh/playfab-party-intro-networking) 等其他 API 則使用下列技術將其核心記憶體使用量降至最低。

### Berkley (BSD) 通訊端

如果您想繼續使用封鎖式 Berkley 通訊端 API，就需要提高 recv 呼叫的頻率。我們建議使用專用執行緒搭配緊密迴圈，將接收到的資料排入佇列，以便在其他地方處理。理想情況下，執行緒應一律在 recv 呼叫內封鎖；在 recv 呼叫外所花費的任何時間，都可能是核心記憶體使用量在等待您再次呼叫 recv 時成長的時間。通常如果您嘗試在再次呼叫 recv 之前處理資料，您的遊戲可能會落後，而只要資料持續以高速率接收，核心記憶體使用量就會持續成長。我們也建議指定至少 8k 的緩衝區大小，以符合核心緩衝區大小的界限，並協助處理抖動和突發的傳送模式。

### WinSock 重疊 I/O

[WinSock 的重疊 I/O](https://learn.microsoft.com/windows/win32/winsock/overlapped-i-o-and-event-objects-2) 可讓您以非同步方式保持使用者模式接收緩衝區處於擱置狀態。它也可讓核心直接使用您的記憶體緩衝區，並避免額外的記憶體複製 (與 Berkley 通訊端範例不同)，而且只要一律有擱置中的緩衝區，核心就完全不會為接收的資料配置記憶體。此外，使用重疊 I/O 時，您可以將 SO\_RCVBUF 和 SO\_SNDBUF 設定為特殊值 0，這樣大致上可完全避免配置任何傳送/接收核心記憶體。

在幾乎所有情況下，這種方法都是管理通訊端所使用記憶體的最佳方式。

### Registered I/O

[Registered I/O](https://learn.microsoft.com/previous-versions/windows/it-pro/windows-server-2012-r2-and-2012/hh997032\(v=ws.11\)) 是一個複雜的網路 API，可提供最低的延遲，並保證傳送和接收作業不使用任何核心記憶體。它可讓您設定多個由核心直接使用的接收/傳送緩衝區，以確保您一律有緩衝區可供輸入資料使用。

<a id="ID4E3CAC" />

## 最大 UDP 傳輸單位大小

雖然 Microsoft Game Development Kit (GDK) 中存在理論上的最大承載大小，但實際上特定連線的最大值取決於網路連線類型。它可能會在遊戲執行時變化。與其嘗試判斷實際的最大傳輸單位 (MTU) 並在遊戲執行時因應 MTU 的變更，您應該將網路程式碼設計為假設每個封包的最大 UDP 承載為 1,384 位元組。此值在所有網路設定下都可安全使用，以避免傳輸中的分割。無論通訊端類型是 IPv4 或 IPv6，我們都建議這麼做。

傳輸大於 1,384 位元組的承載通常需要 IP 層級的封包分割。ISP 以及使用者的家用路由器和裝置對 IP 封包分割的支援並不完善。在這些網路設定中，IP 封包分割不會導致 Winsock API 失敗。分割反而會在您的遊戲中呈現為封包遺失。若要避免 IP 層級的封包分割，請使用 1,384 位元組作為封包承載的安全上限。

為了確保您的遊戲避免分割，並協助您的遊戲符合有關最低多人遊戲網路需求的相關 XBOX 需求，您應該將通訊端選項 `IP_DONTFRAGMENT` 和 `IP_USER_MTU` 套用至遊戲開啟的每個通訊端。只有當 [XGameRuntimeIsFeatureAvailable(XGameRuntimeFeature::XNetworking)](/zh-TW/reference/system/xgameruntimefeature/functions/xgameruntimeisfeatureavailable)  API 傳回 `true` 時，Microsoft Game Development Kit (GDK) 遊戲才能使用這些旗標。如果無法使用 `XNetworking` 功能，`setsockopt` 呼叫就會失敗。以下是如何設定這兩個通訊端選項的範例。

```cpp theme={null}

HRESULT
ApplyFragmentationSocketOptions(
    SOCKET s
)
{
    int value = 1;
    int error = setsockopt(s, IPPROTO_IP, IP_DONTFRAGMENT, (char *)&value, sizeof(value));
    if (error == SOCKET_ERROR)
    {
        return HRESULT_FROM_WIN32(WSAGetLastError());
    }

    value = 1384;
    error = setsockopt(s, IPPROTO_IP, IP_USER_MTU, (char *)&value, sizeof(value));
    if (error == SOCKET_ERROR)
    {
        return HRESULT_FROM_WIN32(WSAGetLastError());
    }

    return S_OK;
}
```

## 另請參閱

* [Windows Sockets 2 (Winsock)](https://learn.microsoft.com/windows/desktop/WinSock/windows-sockets-start-page-2)
* [網路初始化和連線能力](/zh-TW/build/console-features/networking/initialization-connectivity-networking)
* [慣用 UDP 多人遊戲連接埠](/zh-TW/build/console-features/networking/game-mesh/preferred-local-udp-multiplayer-port-networking)
* [PlayFab Party](/zh-TW/build/console-features/networking/game-mesh/playfab-party-intro-networking)
* [PC 連接埠行為](/zh-TW/build/console-features/networking/game-mesh/pc-port-behavior)
* [XBOX 主機連接埠行為 (NDA 主題)](/zh-TW/build/console-features/networking/game-mesh/xbox-console-port-behavior)


## Related topics

- [GDK 中的 Windows Sockets 简介](/zh-CN/build/console-features/networking/game-mesh/winsock-intro-networking.md)
- [Introduction to Windows Sockets in the GDK](/build/console-features/networking/game-mesh/winsock-intro-networking.md)
- [GDK의 Windows Sockets 소개](/ko/build/console-features/networking/game-mesh/winsock-intro-networking.md)
- [Introducción a Windows Sockets en el GDK](/es/build/console-features/networking/game-mesh/winsock-intro-networking.md)
- [GDK での Windows Sockets の紹介](/ja-jp/build/console-features/networking/game-mesh/winsock-intro-networking.md)
