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

# 偵測網路初始化狀態

> 偵測網路初始化狀態

## 網路初始化

使用本文了解如何在 Microsoft Game Development Kit (GDK) 遊戲中擷取網路連線能力和初始化資訊。這些遊戲通常會在核心 OS 元件和網路服務執行之前就已啟動。因此，在遊戲啟動後過早嘗試呼叫大部分網路和安全性 API (包括 `WinSock`、`WinHTTP`、`BCrypt`、`WinCrypt`、`schannel` 和 `IPHLPAPI`)，會導致不確定的行為。此行為可能包括非預期的失敗、未初始化的傳回值、任意的封包遺失，以及可能的記憶體損毀和當機。

為了避免這種不確定的行為，Microsoft Game Development Kit (GDK) 遊戲應使用 [XNetworkingGetConnectivityHint](/zh-TW/reference/networking/xnetworking/functions/xnetworkinggetconnectivityhint) 和 [XNetworkingRegisterConnectivityHintChanged](/zh-TW/reference/networking/xnetworking/functions/xnetworkingregisterconnectivityhintchanged) 函式。特別是，`XNetworkingConnectivityHint::networkInitialized` 欄位會指出網路是否已初始化。遊戲應等待 `networkInitialized` 欄位變為 `true`，然後再呼叫網路和安全性 API。

許多中介軟體程式庫也會在內部使用網路和安全性 API；即使是非網路的中介軟體，也可能使用網路堆疊進行遙測或偵錯。請洽詢中介軟體提供者，了解每種情況下該如何處理。如果中介軟體本身不會等待網路初始化，您可能必須延遲載入中介軟體，直到網路初始化為止。Microsoft Game Development Kit (GDK) 中的數個程式庫，例如 [XSAPI](https://learn.microsoft.com/windows/uwp/xbox-live/xsapi-flat-c) 和 [Azure PlayFab Party](/zh-TW/build/console-features/networking/game-mesh/playfab-party-intro-networking)，都要求您在使用之前等待網路初始化。

## HTTP 堆疊順序

`xCurl` 和 `libHttpClient` 是本文件集所涵蓋的 HTTP 程式庫中，唯一會自動管理網路初始化的程式庫。如果您的遊戲使用任何其他 HTTP 堆疊，請明確定義啟動順序。安全的模式如下：

1. 查詢目前的連線能力提示，或註冊連線能力變更。
2. 等待 `XNetworkingConnectivityHint::networkInitialized` 變為 `true`。
3. 初始化 `WinSock` 及任何其他網路相依性。
4. 存取憑證狀態並設定信任。
5. 建立 HTTP 堆疊並開始發出要求。

網路就緒狀態應該優先處理。過早啟動 `WinSock`、憑證狀態或 HTTP 狀態，可能會產生難以診斷的失敗，因為可見的錯誤通常會比根本原因更晚出現。

下列範例顯示遊戲自有 HTTP 堆疊啟動順序中的前幾個步驟。它會在啟動 `WinSock` 之前直接查詢 `XNetworkingConnectivityHint`。

```cpp theme={null}
HRESULT InitializeNetworkingDependencies()
{
    XNetworkingConnectivityHint connectivityHint{};
    HRESULT hr = XNetworkingGetConnectivityHint(&connectivityHint);
    if (FAILED(hr))
    {
        return hr;
    }

    if (!connectivityHint.networkInitialized)
    {
        // Try again after your title receives a connectivity change notification.
        return E_PENDING;
    }

    WSADATA wsaData{};
    int winsockResult = WSAStartup(MAKEWORD(2, 2), &wsaData);
    if (winsockResult != 0)
    {
        return HRESULT_FROM_WIN32(winsockResult);
    }

    return S_OK;
}
```

這些步驟成功之後，請建立您的 HTTP 堆疊物件，然後在發出要求之前套用任何堆疊特定的信任設定。對於非 Schannel 堆疊，這可能包括載入偵錯工具所需的 Proxy 憑證。

## 暫停與繼續

此外，遊戲的暫停/繼續週期會將 `networkInitialized` 欄位重設回 `false`。暫停時，遊戲應清除所有網路和安全性元件的所有控制代碼，並停止所有網路作業。如需各網路 API 在暫停時的需求詳細資訊，請參閱該 API 的概觀頁面。繼續時，遊戲應再次等待 `networkInitialized` 欄位變為 `true`，然後再嘗試重新建立連線並使用任何網路或安全性 API。我們建議繼續時的網路初始化路徑與遊戲初次啟動的路徑相同：在繼續或遊戲啟動時，先等待網路初始化，再啟動您的網路程式碼。不知道暫停/繼續的中介軟體程式庫 (例如 GameChat2 和 Azure PlayFab Party)，必須在暫停時清除，並在繼續時等待網路初始化後重新初始化。

請假設除了 xCurl 之外的每個 HTTP 堆疊都需要明確的生命週期處理。在暫停或關閉時，停止將新的要求排入佇列，並取消或清空進行中的工作。終結不應在暫停後保留的要求控制代碼、工作階段和通訊端。

繼續時，請將網路啟動視為全新的初始化路徑。在重新建立 HTTP 狀態或重新註冊接聽程式之前，再次等待 `networkInitialized`。與長時間存在的封鎖呼叫相比，以可取消、非封鎖工作為基礎的設計，在暫停期間更容易乾淨地回復。

## 測試網路初始化

無論是繼續或遊戲啟動，網路初始化通常需要幾秒鐘，並會根據主機類型和使用者的網路環境而有所不同。在開發期間，網路初始化幾乎是即時完成的。這可能會隱藏遊戲中各個部分未正確等待網路初始化的問題。若要測試網路初始化情境，請使用 `xbconfig NetworkInitDelayInSeconds=30` 為網路初始化程序新增任意延遲。使用此設定時，請務必在每次測試之間使用 `xbapp terminate /full` 完整重新啟動您的遊戲。完成測試後，請將 `NetworkInitDelayInSeconds` 設回 `0`。

對於會建立自有網路狀態的 HTTP 堆疊，請在您的測試涵蓋範圍中至少包含下列情境：

* 冷開機
* 在要求作用中時暫停
* 在乾淨暫停後繼續
* Quick Resume 或同等的還原流程
* 在暫停和繼續邊界前後的網路中斷連線

## 網路初始化程式碼範例

下列程式碼範例示範如何以即時、安全的方式輪詢網路是否已初始化。

```cpp theme={null}

bool IsNetworkInitialized()
{
    XNetworkingConnectivityHint connectivityHint;
    if (SUCCEEDED(XNetworkingGetConnectivityHint(&connectivityHint)))
    {
        return connectivityHint.networkInitialized;
    }
    return false;
}

```

下列程式碼範例示範遊戲如何封鎖直到網路初始化為止。

```cpp theme={null}
static
void
NetworkConnectivityHintChangedCallback(
    _In_ void* context,
    _In_ const XNetworkingConnectivityHint* connectivityHint
    )
{
    HANDLE networkInitializedEvent = static_cast<HANDLE>(context);
    if (connectivityHint->networkInitialized)
    {
        (void)SetEvent(networkInitializedEvent);
    }
}

HRESULT EnsureNetworkInitialized()
{
    HRESULT hr = S_OK;
    XNetworkingConnectivityHint connectivityHint;
    XTaskQueueHandle queue;

    hr = XTaskQueueCreate(XTaskQueueDispatchMode::Immediate, XTaskQueueDispatchMode::Immediate, &queue);
    if (SUCCEEDED(hr))
    {
        // Use the new XNetworking APIs to check if the network is initialized.
        hr = XNetworkingGetConnectivityHint(&connectivityHint);
        if (SUCCEEDED(hr))
        {
            if (!connectivityHint.networkInitialized)
            {
                // The network isn't initialized. Wait until the network becomes initialized.
                HANDLE networkInitializedEvent = CreateEvent(nullptr, TRUE, FALSE, nullptr);
                if (networkInitializedEvent != nullptr)
                {
                    XTaskQueueRegistrationToken token;
                    hr = XNetworkingRegisterConnectivityHintChanged(queue, networkInitializedEvent, NetworkConnectivityHintChangedCallback, &token);
                    if (SUCCEEDED(hr))
                    {
                        DWORD result = WaitForSingleObjectEx(networkInitializedEvent, INFINITE, FALSE);
                        if (result != WAIT_OBJECT_0)
                        {
                            hr = HRESULT_FROM_WIN32(GetLastError());
                        }

                        XNetworkingUnregisterConnectivityHintChanged(token, true);
                    }

                    CloseHandle(networkInitializedEvent);
                }
                else
                {
                    hr = HRESULT_FROM_WIN32(GetLastError());
                }
            }
        }

        XTaskQueueCloseHandle(queue);
    }

    return hr;
}

```

## 網路資訊

Microsoft Game Development Kit (GDK) 遊戲中的網路資訊，可以使用 [XNetworkingGetConnectivityHint](/zh-TW/reference/networking/xnetworking/functions/xnetworkinggetconnectivityhint) API 擷取。

[XNetworkingGetConnectivityHint](/zh-TW/reference/networking/xnetworking/functions/xnetworkinggetconnectivityhint) API 會傳回整個裝置的網路連線能力層級、資料限制、有線與無線連線類型，以及網路是否已初始化等資訊。它是即時、安全的 API，會立即傳回目前的資訊。您可以使用 [XNetworkingRegisterConnectivityHintChanged](/zh-TW/reference/networking/xnetworking/functions/xnetworkingregisterconnectivityhintchanged) 和 [XNetworkingUnregisterConnectivityHintChanged](/zh-TW/reference/networking/xnetworking/functions/xnetworkingunregisterconnectivityhintchanged) 函式接聽變更。

下列程式碼範例示範如何使用 [XNetworkingGetConnectivityHint](/zh-TW/reference/networking/xnetworking/functions/xnetworkinggetconnectivityhint) 函式查詢目前網路狀態的相關資訊。

```cpp theme={null}

XNetworkingConnectivityHint connectivityHint;
if (SUCCEEDED(XNetworkingGetConnectivityHint(&connectivityHint)))
{
    printf(L"network initialized %u\n", connectivityHint.networkInitialized);
    printf(L"network connectivity level hint %u\n", connectivityHint.connectivityLevel);
    printf(L"network connectivity cost hint %u\n", connectivityHint.connectivityCost);
    printf(L"network approaching data limit %u\n", connectivityHint.approachingDataLimit);
    printf(L"network over data limit %u\n", connectivityHint.overDataLimit);
    printf(L"device is roaming %u\n", connectivityHint.roaming);
    switch (connectivityHint.ianaInterfaceType) {
    case IF_TYPE_ETHERNET_CSMACD:
        printf(L"network type is wired\n");
            break;
    case IF_TYPE_IEEE80211:
        printf(L"network type is wireless\n");
        break;
    case IF_TYPE_WWANPP:
    case IF_TYPE_WWANPP2:
        printf(L"network type is broadband\n");
        break;
    default:
        printf(L"network type is unusually esoteric %u\n", connectivityHint.connectivityLevel);
        break;
    }
}

```

## 網路連線能力最佳做法

傳回的 [XNetworkingConnectivityHint](/zh-TW/reference/networking/xnetworking/structs/xnetworkingconnectivityhint) 結構中，除了 `XNetworkingConnectivityHint::networkInitialized` 欄位之外的欄位都是提示。它們是裝置對網路目前狀態的盡力推測，以裝置上觀察到的網路流量啟發學習法為依據。

`XNetworkingConnectivityLevelHint` 的狀態代表一般網路層級的近似值，以簡化遊戲的連線能力邏輯。在網路環境數分鐘內未變更的穩定狀態下，遊戲可以預期 `XNetworkingConnectivityLevelHint::None` 反映網路媒體中斷連線及一般缺乏連線能力的情況。其他狀態並不代表是否能連線到您特定的遊戲端點。

因此，我們建議在等待網路初始化之後，無論 `XNetworkingConnectivityHint::connectivityLevelHint` 欄位的狀態為何，都使用 `WinSock` 和/或 `WinHTTP` 嘗試建立與您端點的連線。如果這些 API 之後失敗，我們建議您再使用 [XNetworkingGetConnectivityHint](/zh-TW/reference/networking/xnetworking/functions/xnetworkinggetconnectivityhint) API，以進行更多 UI 和診斷報告。接著，您應等待網路連線能力層級變更，然後再重試。

## 擷取進階網路資訊

大部分 Microsoft Game Development Kit (GDK) 遊戲應使用 [XNetworkingGetConnectivityHint](/zh-TW/reference/networking/xnetworking/functions/xnetworkinggetconnectivityhint) API 搭配 `WinSock` API，來擷取網路狀態和基本網路資訊 (例如 IP 位址)。如果您需要更多資訊，GDK 中提供低階的 [IP Helper API](https://learn.microsoft.com/windows/desktop/IpHlp/ip-helper-start-page)。

一般而言，在 Microsoft Game Development Kit (GDK) 中使用 `IP Helper` API 的方式，與在 Win32 程式中使用此 API 的方式相同。

1. 在您的原始程式檔中，於 `#include <winsock2.h>` 之後加入 `#include <iphlpapi.h>`。

2. 連結 `XGamePlatform.lib`，而不是直接連結 `Ws2_32.lib` 和 `Iphlpapi.lib`。

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

在 XBOX 主機上，由於底層平台抽象化，使用 `IP Helper` API 時某些資訊並不準確。這包括但不限於下列各項：

* MAC 位址一律為 `AA-AA-AA-AA-AA-AA`。
* 無論底層網路連線類型為何，所有介面一律回報為有線介面。真正的介面類型只能從 [XNetworkingGetConnectivityHint](/zh-TW/reference/networking/xnetworking/functions/xnetworkinggetconnectivityhint) 擷取。

## 不支援的網路連線能力 API

Microsoft Game Development Kit (GDK) 遊戲不支援下列網路連線能力 API，這些遊戲應改用 [XNetworkingGetConnectivityHint](/zh-TW/reference/networking/xnetworking/functions/xnetworkinggetconnectivityhint) API 來判斷網路連線能力。

* [Windows.Networking.Connectivity 命名空間](https://learn.microsoft.com/uwp/api/windows.networking.connectivity)

* [網路清單管理員](https://learn.microsoft.com/windows/desktop/nla/portal)

## 另請參閱

[XNetworkingGetConnectivityHint](/zh-TW/reference/networking/xnetworking/functions/xnetworkinggetconnectivityhint)

[XNetworkingRegisterConnectivityHintChanged](/zh-TW/reference/networking/xnetworking/functions/xnetworkingregisterconnectivityhintchanged)

[XNetworkingUnregisterConnectivityHintChanged](/zh-TW/reference/networking/xnetworking/functions/xnetworkingunregisterconnectivityhintchanged)

[Windows Sockets 2 (Winsock)](https://learn.microsoft.com/windows/desktop/WinSock/windows-sockets-start-page-2)

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

[IP Helper API](https://learn.microsoft.com/windows/desktop/IpHlp/ip-helper-start-page)


## Related topics

- [初始化 GDK](/zh-CN/build/steam-porting-guide/initializing-the-gdk.md)
- [XR052 使用者狀態與遊戲存檔位置、漫遊及相依性](/zh-TW/publishing/certification/fma/xr-052.md)
- [目标会话初始化和 QoS](/zh-CN/services/xbox-services/multiplayer/matchmaking/concepts/live-matchmaking-target-session.md)
- [检测网络初始化状态](/zh-CN/build/console-features/networking/initialization-connectivity-networking.md)
- [媒體驗證測試步驟](/zh-TW/publishing/game-publishing/concepts/certification/certification-media-validation-test-steps.md)
