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

# WinHTTP 概觀

> WinHTTP 概觀

本文說明如何在 Microsoft Game Development Kit (GDK) 遊戲中使用 [Windows HTTP 服務 (WinHTTP)](https://learn.microsoft.com/windows/desktop/winhttp/winhttp-start-page) 功能。這是適用於 PC 和 XBOX 主機 Microsoft Game Development Kit (GDK) 遊戲的較低層級 HTTP 用戶端 API。您可以使用它建立一般的 HTTP 和 WebSocket 服務端點。

由於它屬於較低層級，因此需要考量和實作的步驟較多，才能為您的遊戲實現安全且穩健的通訊。我們建議您的遊戲實作遵循所有[通訊安全性最佳做法 (NDA 文章)](/zh-TW/build/game-principles/security/communication-security-overview)。

## WinHTTP 版本差異

一般而言，Microsoft Game Development Kit (GDK) 遊戲與 WinHTTP 互動的方式，與 Win32 應用程式與 WinHTTP 互動的方式相同。

開發 Microsoft Game Development Kit (GDK) 遊戲時，只能使用 WinHTTP 的扁平 C/C++ API。這表示 HTTP 功能必須建置在此 HTTP 用戶端 API 之上。

## 將 WinHTTP 新增至您的 XBOX 主機專案

在主機上，您應在原始程式檔中 `#include <winhttp.h>`。您必須連結 `XGamePlatform.lib`，而非直接連結 `Winhttp.lib`。只有 `WINAPI_PARTITION_GAMES` API 系列下的 API 能在 Microsoft Game Development Kit (GDK) 遊戲中運作。在 Windows PC 上，您應繼續連結 `Winhttp.lib`。

如需如何將 WinHTTP 整合到 Microsoft Game Development Kit (GDK) 遊戲中的範例，請參閱 [SimpleWinHttp 範例](https://aka.ms/gdkdl)。它為您自己的 WinHTTP 實作提供了穩固的起點，並包含 `WinHttpManager` 類別。它公開了簡單的非同步 API 介面。

## 網路初始化與 WinHTTP

在您的遊戲第一次呼叫 [WinHttpOpen](https://learn.microsoft.com/windows/desktop/api/winhttp/nf-winhttp-winhttpopen) 之前，Microsoft Game Development Kit (GDK) 遊戲必須確保網路堆疊已初始化。如果在遊戲啟動過程中過早呼叫 `WinHttpOpen`，`WinHttpOpen` 或後續的 WinHTTP 呼叫可能會以非決定性的方式失敗或當機。在網路宣告為已初始化之前，要求可能看似成功但實際上失敗，反之亦然。如需如何判斷網路堆疊何時初始化的詳細資料，請參閱[網路初始化](/zh-TW/build/console-features/networking/initialization-connectivity-networking#network-initialization)。

## 遊戲暫停/繼續與 WinHTTP

收到遊戲暫停通知時，遊戲應啟動關閉所有 WinHTTP 控制代碼的程序。WinHTTP 控制代碼清除是非同步的。因此，您應依照下列順序關閉控制代碼：先關閉所有要求控制代碼，接著關閉所有連線控制代碼，最後關閉所有工作階段控制代碼。WinHTTP 控制代碼清除採用非同步方式，是為了確保通知執行緒的安全性。雖然是非同步的，但 WinHTTP 控制代碼清除不會延遲任何時間，因此能輕鬆符合一秒的暫停延期逾時限制。

繼續時，遊戲應遵循上述「網路初始化與 WinHTTP」一節所述的相同程序，並等候網路回到就緒狀態，再繼續使用 WinHTTP。暫停和繼續事件之間可能已經過很長一段時間，因此網路需要再次穩定，WinHTTP API 才會再次具有決定性。

## 記憶體和並行考量

並行 WinHTTP 要求的數目應一律保持在八個以下，以確保 WinHTTP 內的非同步狀態能正確運作並維持在其記憶體預算內。此限制適用於遊戲執行階段內的所有並行作業，包括來自 XBOX services API 和 `XCurl` 的呼叫。

作為 [WinSock 記憶體考量](/zh-TW/build/console-features/networking/game-mesh/winsock-intro-networking#SocketMemory)的延伸，您應確保接收資料時，一律有以 `WinHttpReadData` 擱置的緩衝區 (或正在等候 `WinHttpQueryDataAvailable` 呼叫的回呼)，以便盡快將資料從核心模式記憶體集區傳輸到您的使用者模式處理程序，並將 HTTP 作業所耗用的核心記憶體量降到最低。

`WinHttpQueryHeaders` getter 函式需要暫時性記憶體配置。它會配置大小等於 `lpdwBufferLength` 參數的暫存緩衝區供內部使用 (並在函式傳回前釋放)。因此，您應使用 `WINHTTP_NO_OUTPUT_BUFFER` 雙重呼叫模式，將暫存緩衝區的大小降到最低，並限制同時對 `WinHttpQueryHeaders` 進行的並行呼叫數目，以避免可能導致系統不穩定的過度系統記憶體使用量。標頭的預設大小上限為 64 KB，由 `WINHTTP_OPTION_MAX_RESPONSE_HEADER_SIZE` WinHTTP 選項指定。

## WinHttpOpen 考量

### 旗標

您必須將下表中的旗標傳遞至 [WinHttpOpen](https://learn.microsoft.com/windows/win32/api/winhttp/nf-winhttp-winhttpopen)。

| 參數 | 值 |
| - | - |
| `dwAccessType` | `WINHTTP_ACCESS_TYPE_AUTOMATIC_PROXY` |
| `pszProxyW` | `WINHTTP_NO_PROXY_NAME` |
| `pszProxyBypassW` | `WINHTTP_NO_PROXY_BYPASS` |
| `dwFlags` | `WINHTTP_FLAG_SECURE_DEFAULTS` |

結合 `WINHTTP_ACCESS_TYPE_AUTOMATIC_PROXY`、`WINHTTP_NO_PROXY_NAME` 和 `WINHTTP_NO_PROXY_BYPASS`，可讓 Microsoft Game Development Kit (GDK) 平台自動處理 [Fiddler](/zh-TW/build/console-features/networking/tools/fiddler-setup-networking) 等 Proxy 及其他特殊情況的網路環境。

`WINHTTP_FLAG_SECURE_DEFAULTS` 旗標是一個新旗標，旨在藉由設定建議的安全連線行為，協助 Microsoft Game Development Kit (GDK) 遊戲遵循安全性最佳做法。它可在 XBOX One 主機上使用，並將在未來的 Windows 作業系統更新中於 Windows PC 上提供。嘗試在現有的 Windows 作業系統版本上傳遞 `WINHTTP_FLAG_SECURE_DEFAULTS` 會導致無效參數失敗。此旗標有一個重大的副作用：它會強制 WinHTTP 進入非同步模式，因為此旗標隱含地包含 `WINHTTP_FLAG_ASYNC` 旗標。在不支援此旗標的 Windows PC 作業系統版本上，您應改為傳遞 `WINHTTP_FLAG_ASYNC`，以將 WinHTTP 實作其餘部分的差異降到最低。

<Note>`WINHTTP_FLAG_SECURE_DEFAULTS` 旗標需要將相符的 `WINHTTP_FLAG_SECURE` 旗標傳遞給 `WinHttpOpenRequest`，並會封鎖未加密的 HTTP 要求。在用於內部偵錯和測試的開發套件上，您可以建立 WinHTTP 工作階段控制代碼，並對 `WinHttpOpen` 指定 `WINHTTP_FLAG_ASYNC` 旗標。此旗標可讓您在開發期間不對 `WinHttpOpenRequest` 指定 `WINHTTP_FLAG_SECURE` 旗標，以發出未加密的 HTTP 要求。對於非偵錯流量，您仍應使用以 `WINHTTP_FLAG_SECURE_DEFAULTS` 開啟的工作階段控制代碼，以符合您的遊戲在 RETAIL 中看到的要求行為。</Note>

### WINHTTP\_OPTION\_SECURE\_PROTOCOLS

使用 `WinHttpOpen` 建立新的工作階段控制代碼後，您必須以 `WINHTTP_OPTION_SECURE_PROTOCOLS` 選項呼叫 [WinHttpSetOption](https://learn.microsoft.com/windows/win32/api/winhttp/nf-winhttp-winhttpsetoption)，並傳遞對應的 `XNetworkingSecurityInformation::enabledHttpSecurityProtocolFlags`，該值是針對此工作階段控制代碼將使用的相符 URL 呼叫 [XNetworkingQuerySecurityInformationForUrlUtf16Async](/zh-TW/reference/networking/xnetworking/functions/xnetworkingquerysecurityinformationforurlutf16async) 所擷取。您也應將 [XNetworkingSecurityInformation](/zh-TW/reference/networking/xnetworking/structs/xnetworkingsecurityinformation) 結構儲存在您的內容物件上，以供稍後驗證 TLS/SSL 交握時使用。

### 快取工作階段控制代碼

透過 `WinHttpOpen` 建立的 HTTP 工作階段控制代碼在記憶體方面成本很高，且會產生延遲第一個 HTTP 要求的大量啟動成本。我們建議您在遊戲內盡可能快取 HTTP 工作階段控制代碼，以避免這些成本。

不過，無法變更工作階段控制代碼上的 `WINHTTP_OPTION_SECURE_PROTOCOLS` 選項。您應保留將 `XNetworkingSecurityInformation::enabledHttpSecurityProtocolFlags` 值對應至 WinHTTP 工作階段控制代碼的快取，以確保每個不同的安全通訊協定旗標都有不同的工作階段控制代碼。

您的遊戲所維護的快取必須在收到暫停通知時清除，並應在繼續時 (等候網路完成初始化之後) 從頭重建。

## WinHttpConnect 考量

與工作階段控制代碼不同，透過 [WinHttpConnect](https://learn.microsoft.com/windows/win32/api/winhttp/nf-winhttp-winhttpconnect) 建立的連線控制代碼絕不應快取。應為每個新要求和/或重試嘗試建立新的控制代碼。WinHTTP 連線控制代碼雖然名為連線，但與基礎伺服器傳輸控制通訊協定 (TCP) 連線沒有任何關係。WinHTTP 會透過工作階段控制代碼管理基礎伺服器連線的存留期，並盡可能自動為新的連線控制代碼重複使用已開啟的伺服器連線。

### URL 標準化

WinHTTP 預期所有 URL 都已標準化為 a-z、A-Z 和 0-9 的 US-ASCII 字元。如需標準化的詳細資訊，請參閱 [WinHTTP 中的統一資源定位器 (URL)](https://learn.microsoft.com/windows/win32/winhttp/uniform-resource-locators--urls--in-winhttp)。我們建議盡可能以標準化形式硬式編碼您的遊戲所使用的 URL。此形式可避免使用 [WinHttpCrackUrl](https://learn.microsoft.com/windows/win32/api/winhttp/nf-winhttp-winhttpcrackurl) 和 [WinHttpCreateUrl](https://learn.microsoft.com/windows/win32/api/winhttp/nf-winhttp-winhttpcreateurl) 函式動態標準化 URL 所產生的記憶體配置和效能問題。

### URL 分割

WinHTTP 需要將以 Null 結尾的主機名稱字串傳遞給 `WinHttpConnect`，而路徑和物件則傳遞給 `WinHttpOpenRequest`。您的遊戲在某些地方必須傳遞完整 URL (即串連的主機名稱和路徑)，而在其他地方只傳遞主機名稱或路徑。我們建議您在遊戲中硬式編碼這兩者，以避免需要使用 [WinHttpCrackUrl](https://learn.microsoft.com/windows/win32/api/winhttp/nf-winhttp-winhttpcrackurl) 和 [WinHttpCreateUrl](https://learn.microsoft.com/windows/win32/api/winhttp/nf-winhttp-winhttpcreateurl) 動態串連或分割 URL。

## WinHttpOpenRequest 考量

與 WinHTTP 連線控制代碼類似，透過 [WinHttpOpenRequest](https://learn.microsoft.com/windows/win32/api/winhttp/nf-winhttp-winhttpopenrequest) 函式建立的 WinHTTP 要求控制代碼絕不應快取。應為每個新要求和/或重試嘗試建立新的控制代碼。

作為安全性最佳做法，遊戲在呼叫 `WinHttpOpenRequest` 函式時，應一律為 `dwFlags` 參數傳遞 `WINHTTP_FLAG_SECURE` 旗標。

## 擷取及套用 XBOX services 權杖

Microsoft Game Development Kit (GDK) 遊戲不會自動插入權杖。相反地，遊戲應使用 Microsoft Game Development Kit (GDK) [XUser](/zh-TW/reference/system/xuser/xuser_members) API 擷取 XBOX services 驗證權杖和簽章。遊戲取得使用者之後，應呼叫 [XUserGetTokenAndSignatureUtf16Async](/zh-TW/reference/system/xuser/functions/xusergettokenandsignatureutf16async)，為每個個別要求擷取權杖和簽章字串。接著，應在呼叫 `WinHttpAddRequestHeadersEx`、[WinHttpSendRequest](https://learn.microsoft.com/windows/desktop/api/winhttp/nf-winhttp-winhttpsendrequest) 或 [WinHttpAddRequestHeaders](https://learn.microsoft.com/windows/desktop/api/winhttp/nf-winhttp-winhttpaddrequestheaders) 時，將這兩個字串作為標頭傳遞。

為了產生正確的簽章，[XUserGetTokenAndSignatureUtf16Async](/zh-TW/reference/system/xuser/functions/xusergettokenandsignatureutf16async) 預期遊戲傳遞所有標頭和整個本文。對於具有大型本文的 `POST` 或 `PUT`，遊戲可以傳遞在 Partner Center 中設定的本文子集。如需詳細資訊，請參閱 [Web 服務 (NDA 主題)](/zh-TW/services/xbox-services/fundamentals/s2s-auth-calls/custom-service-config/web-services/live-web-services-nav)。目前，XBOX 網路並未提供擷取此設定的機制。用戶端應硬式編碼這些值，或透過自訂的遊戲專屬端點擷取這些值。

[XUserGetTokenAndSignatureUtf16Async](/zh-TW/reference/system/xuser/functions/xusergettokenandsignatureutf16async) 會在內部執行所有必要的快取，且應在每次 HTTP 嘗試 (包括重試) 時呼叫。如果遊戲對任何 HTTP 要求收到 401 Unauthorized HTTP 回應狀態碼，遊戲應重試要求，並強制重新整理 XBOX services 驗證權杖。若要重新整理，請使用 [XUserGetTokenAndSignatureUtf16Async](/zh-TW/reference/system/xuser/functions/xusergettokenandsignatureutf16async) 擷取新權杖，並傳遞 [XUserGetTokenAndSignatureOptions::ForceRefresh](/zh-TW/reference/system/xuser/enums/xusergettokenandsignatureoptions) 列舉值。

遊戲取得透過呼叫 [XUserGetTokenAndSignatureUtf16Async](/zh-TW/reference/system/xuser/functions/xusergettokenandsignatureutf16async) 擷取的 [XUserGetTokenAndSignatureUtf16Data](/zh-TW/reference/system/xuser/structs/xusergettokenandsignatureutf16data) 之後，必須將 `XUserGetTokenAndSignatureUtf16Data::Token` 和 `XUserGetTokenAndSignatureUtf16Data::Signature` 轉換為要傳遞至 WinHTTP 的 HTTP 標頭。新增了新的 WinHTTP API `WinHttpAddRequestHeadersEx`，專門用來降低 Microsoft Game Development Kit (GDK) 遊戲的複雜度。下列範例示範如何使用這個新 API。此新 API 可在 XBOX One 主機上使用，並將在未來的 Windows 作業系統更新中於 Windows PC 上提供。在主機上，我們建議您使用 `WinHttpAddRequestHeadersEx`，以避免額外的配置和字串格式變更。

```cpp theme={null}
HRESULT
AddTokenAndSignatureDataToHttpRequest(
    XUserGetTokenAndSignatureUtf16Data* userTokenAndSignatureData,
    HINTERNET requestHandle
    )
{
    WINHTTP_EXTENDED_HEADER winhttpHeader[2];
    winhttpHeader[0].pwszName = L"Authorization";
    winhttpHeader[0].pwszValue = userTokenAndSignatureData->token;
    winhttpHeader[1].pwszName = L"Signature";
    winhttpHeader[1].pwszValue = userTokenAndSignatureData->signature;
    return HRESULT_FROM_WIN32(WinHttpAddRequestHeadersEx(
        m_handshakeRequest,
        WINHTTP_ADDREQ_FLAG_ADD,
        WINHTTP_EXTENDED_HEADER_FLAG_UNICODE,
        0,
        tokenAndSignature->signatureCount ? 2 : 1,
        winhttpHeader));
}

```

<Note>裝置或已登入的帳戶必須能夠存取其所設定的沙箱。否則，`XUserGetTokenAndSignatureUtf16Data` 會失敗。</Note>

### 使用 XBOX 網路安全性授權清單 (NSAL)

XBOX 網路使用 NSAL 確保用戶端與您的 Web 服務建立安全且經過驗證的連線。遊戲會在 Partner Center 中將 NSAL 的內容作為其設定的一部分進行管理。如需詳細資訊，請參閱[在 Partner Center 設定 Web 服務 (NDA 主題)](/zh-TW/services/xbox-services/fundamentals/s2s-auth-calls/custom-service-config/web-services/live-web-services)。接著會自動為每個遊戲下載 NSAL 設定。它既用於產生適當的 XBOX services 權杖，也用於對您遊戲的特定端點執行憑證關聯。}

## WinHTTP 非同步狀態機器考量

主機上的 WinHTTP 非同步狀態機器與 Windows PC 上的相同。若要向一或多個通知註冊回呼函式，請使用 [WinHttpSetStatusCallback](https://learn.microsoft.com/windows/win32/api/winhttp/nf-winhttp-winhttpsetstatuscallback) 函式。基於偵錯目的，我們建議對 `dwNotificationFlags` 參數使用 `WINHTTP_CALLBACK_FLAG_ALL_NOTIFICATIONS` 旗標，因為 WinHTTP 對於其正在執行的動作相當詳細且透明。雖然大部分通知不需要您採取任何動作，但記錄資料有助於找出問題的根本原因。

WinHTTP 使用單一執行緒處理通知。遊戲應盡可能避免封鎖任何通知函式，因為這會讓處理程序內的所有 HTTP 要求都無法進行。未處理的通知也可能增加核心模式記憶體，進而導致當機。

WinHTTP 不會複製您的傳送或接收緩衝區，並要求您在對應的完成回呼之前保持這些緩衝區為已配置狀態。請確保從呼叫 [WinHttpSendRequest](https://learn.microsoft.com/windows/win32/api/winhttp/nf-winhttp-winhttpsendrequest) 到收到對應的 `WINHTTP_CALLBACK_STATUS_SENDREQUEST_COMPLETE` 通知為止，傳送緩衝區都保持已配置且有效。同樣地，每次呼叫 [WinHttpReadData](https://learn.microsoft.com/windows/win32/api/winhttp/nf-winhttp-winhttpreaddata) 時，請確保接收緩衝區在收到對應的 `WINHTTP_CALLBACK_STATUS_READ_COMPLETE` 通知之前都保持已配置且有效。我們也建議使用至少 8 KB 大小的接收緩衝區，以避免可能導致堆疊耗盡的遞迴問題。

遊戲也應持續進行非同步的 `WinHttpQueryDataAvailable`/`WinHttpReadData` 循環，並且不在任何時間封鎖 WinHTTP 回呼，以確保 WinHTTP 緩衝區正確清空。

### 驗證傳輸層安全性 (TLS)/安全通訊端層 (SSL) 交握

作為安全性最佳做法，遊戲應執行 TLS/SSL 交握驗證，且只使用 TLS 1.2。

額外的驗證會在 `WINHTTP_CALLBACK_STATUS_SENDING_REQUEST` 通知內執行。在此通知內，您必須呼叫 [XNetworkingVerifyServerCertificate](/zh-TW/reference/networking/xnetworking/functions/xnetworkingverifyservercertificate) 函式，並傳入先前對應呼叫 [XNetworkingQuerySecurityInformationForUrlUtf16Async](/zh-TW/reference/networking/xnetworking/functions/xnetworkingquerysecurityinformationforurlutf16async) 所擷取的 [XNetworkingSecurityInformation](/zh-TW/reference/networking/xnetworking/structs/xnetworkingsecurityinformation) 結構。如果憑證鏈結無效，此函式會失敗。您應在回呼完成之前*立即*關閉 WinHTTP 控制代碼，以確保不會與遭入侵的伺服器之間傳輸任何資料。

除了驗證憑證鏈結之外，主機上的 Fiddler 功能也需要 [XNetworkingVerifyServerCertificate](/zh-TW/reference/networking/xnetworking/functions/xnetworkingverifyservercertificate) 函式。

## 偵錯 WinHTTP

[Fiddler](/zh-TW/build/console-features/networking/tools/fiddler-setup-networking) 是檢視及偵錯 WinHTTP 流量的實用工具。若要讓 Fiddler 擷取您的遊戲流量，您必須將 `WINHTTP_ACCESS_TYPE_AUTOMATIC_PROXY`、`WINHTTP_NO_PROXY_NAME` 和 `WINHTTP_NO_PROXY_BYPASS` 旗標傳遞給 `WinHttpOpen`。您也必須在 `WINHTTP_CALLBACK_STATUS_SENDING_REQUEST` 通知回呼內呼叫 [XNetworkingVerifyServerCertificate](/zh-TW/reference/networking/xnetworking/functions/xnetworkingverifyservercertificate)。

<Note>HTTP Monitor 不適用於 Microsoft Game Development Kit (GDK) 遊戲。</Note>

## 參考 API 文件

* [Xuser (API 內容)](/zh-TW/reference/system/xuser/xuser_members)
  * 函式
    * [XUserGetTokenAndSignatureUtf16Async](/zh-TW/reference/system/xuser/functions/xusergettokenandsignatureutf16async)
  * 結構
    * [XUserGetTokenAndSignatureUtf16Data](/zh-TW/reference/system/xuser/structs/xusergettokenandsignatureutf16data)
* [xnetworking (API 內容)](/zh-TW/reference/networking/xnetworking/xnetworking_members)
  * 函式
    * [XNetworkingQuerySecurityInformationForUrlUtf16Async](/zh-TW/reference/networking/xnetworking/functions/xnetworkingquerysecurityinformationforurlutf16async)
    * [XNetworkingVerifyServerCertificate](/zh-TW/reference/networking/xnetworking/functions/xnetworkingverifyservercertificate)
  * 結構
    * [XNetworkingSecurityInformation](/zh-TW/reference/networking/xnetworking/structs/xnetworkingsecurityinformation)

## 另請參閱

[Windows HTTP 服務 (WinHTTP)](https://learn.microsoft.com/windows/desktop/winhttp/winhttp-start-page)

[XSAPI C 概觀 (安全連結)](https://developer.microsoft.com/games/xbox/docs/gdk/atoc-xsapi-c)

[XUser](/zh-TW/reference/system/xuser/xuser_members)

[在 Partner Center 設定 Web 服務 (NDA 文章)](/zh-TW/services/xbox-services/fundamentals/s2s-auth-calls/custom-service-config/web-services/live-web-services)

[XBOX One 主機上的 Fiddler](/zh-TW/build/console-features/networking/tools/fiddler-setup-networking)

[通訊安全性最佳做法概觀 (NDA 文章)](/zh-TW/build/game-principles/security/communication-security-overview)


## Related topics

- [WinHTTP overview](/build/console-features/networking/web-requests/intro-winhttp.md)
- [WinHTTP 概述](/zh-CN/build/console-features/networking/web-requests/intro-winhttp.md)
- [WinHTTP 개요](/ko/build/console-features/networking/web-requests/intro-winhttp.md)
- [WinHTTP の概要](/ja-jp/build/console-features/networking/web-requests/intro-winhttp.md)
- [Información general de WinHTTP](/es/build/console-features/networking/web-requests/intro-winhttp.md)
