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

# MsQuic

> MsQuic

本文介绍如何在 Microsoft 游戏开发工具包 (GDK) 中使用 [MsQuic](https://github.com/microsoft/msquic)。MsQuic 是 [IETF QUIC](https://datatracker.ietf.org/wg/quic/about/) 协议的 Microsoft 实现。它跨平台、以 C 编写，被设计为一个通用 QUIC 库。

QUIC 最初旨在替代诸如 HTTP 这样使用“TLS over TCP”的场景。开发者将其扩展为一个通用的 UDP 数据传输层，适合在单个连接上多路复用实时不可靠数据报消息以及类似 TCP 的可靠流。这样的设计让它作为客户端/服务器传输层，以及作为实时游戏流量数据流的基础，都特别有吸引力。

MsQuic 针对 GDK 游戏进行了定制，同时也可用于多种平台，包括 Windows Server、Linux 桌面与服务器、iOS、Android 和 macOS。

[MsQuic API 文档](https://github.com/microsoft/msquic/blob/main/docs/API.md) 涵盖了许多重要的 MsQuic 概念，并展示了如何对 MsQuic API 面进行编码。

## QUIC 特性

* 所有数据包都被加密，握手使用 TLS 1.3 进行认证。
* 可靠和不可靠应用数据的并行流。
* 首次往返 (0-RTT) 即可交换应用数据。
* 改进的拥塞控制与丢包恢复。
* 客户端 IP 地址或端口变更后仍可保持连接。
* 无状态负载均衡。
* 易于扩展新特性与扩展。

## MsQuic 实现

除针对 GDK 游戏进行定制外，MsQuic 相较于其他 QUIC 实现还有以下多项差异化特性：

* 针对客户端和服务器进行优化。
* 针对最大吞吐量与最小延迟进行优化。
* 异步 IO。
* 支持接收端缩放 (RSS)。
* 支持 UDP 发送和接收合并。

MsQuic 实现了以下 QUIC RFC：

* [RFC 9000](https://datatracker.ietf.org/doc/html/rfc9000)
* [RFC 9001](https://datatracker.ietf.org/doc/html/rfc9001)
* [RFC 9002](https://datatracker.ietf.org/doc/html/rfc9002)

MsQuic 实现了以下 QUIC 草案扩展：

* [Datagram](https://datatracker.ietf.org/doc/html/draft-ietf-quic-datagram)
* [Version Negotiation](https://datatracker.ietf.org/doc/html/draft-ietf-quic-version-negotiation)
* [Load Balancing](https://datatracker.ietf.org/doc/html/draft-ietf-quic-load-balancers)
* [ACK Frequency](https://datatracker.ietf.org/doc/html/draft-ietf-quic-ack-frequency)
* [Perf Testing](https://datatracker.ietf.org/doc/html/draft-banks-quic-performance)

## 获取 MsQuic

Microsoft 在一个开源 GitHub 仓库中托管 MsQuic。请通过其官方发行版本获取 MsQuic，[在此查看](https://github.com/microsoft/msquic/blob/main/docs/Release.md)。XBOX Series X|S 主机支持是在 prerelease/1.9 中加入的，不过对于 GDK 游戏，我们建议尽可能使用最新的官方发布版本。

你可以在特定发行版本的 [Assets](https://github.com/microsoft/msquic/releases) 部分找到该版本的预构建 MsQuic 二进制文件。同一 MsQuic 版本的所有构建风味都彼此完全兼容。虽然 MsQuic 也努力在其发行版本之间保持向后兼容性，但有关不同版本之间的兼容性预期，请参阅 MsQuic 文档和发行说明。

### 基于 GDK 的 PC 游戏

对基于 GDK 的 PC 游戏，请使用 `msquic_windows_x64_Release_openssl` 预构建二进制文件。

PC 上的 GDK 游戏以原生 x64 Win32 应用程序运行。请使用为 x64 平台构建的 MsQuic 版本。在 PC 上，请使用基于 OpenSSL 构建的 MsQuic 版本，因为它支持 GDK 支持的所有 OS 版本；而基于 Schannel 的版本仅支持 Windows 11 及更高版本的操作系统。

### 基于 GDK 的主机游戏

对基于 GDK 的主机游戏，请使用 `msquic_gamecore_console_x64_Release_schannel` 预构建二进制文件。

MsQuic 为 XBOX 主机上基于 GDK 的游戏提供了专用构建风味。该风味将 MsQuic 限制在 `WINAPI_PARTITION_GAMES` 下的 API，并让 MsQuic 链接到 `XGamePlatform.lib`。要使用此构建风味，你必须安装 October 2021 或更新版本的 XGDK。基于 GDK 的主机游戏构建时 MsQuic 使用 Schannel。

<a id="ClientServerAuthentication" />

## 客户端与服务器身份认证

MsQuic 会自动使用与 HTTPS Web 请求相同的身份认证与验证路径来对你的服务器进行身份认证。客户端身份认证应遵循 [安全客户端/服务器通信最佳实践 (NDA 主题)](https://learn.microsoft.com/gaming/gdk/docs/gdk-dev/game-principles/security/communication-security/communication-security-impl/gc-secure-game-mesh-impl#ClientAuthentication) 中列出的最佳实践。

在 MsQuic 中，无论客户端还是服务器，都应使用 [ConfigurationLoadCredential](https://github.com/microsoft/msquic/blob/main/docs/api/ConfigurationLoadCredential.md) API 并配合合适的 [QUIC\_CREDENTIAL\_CONFIG](https://github.com/microsoft/msquic/blob/main/docs/api/QUIC_CREDENTIAL_CONFIG.md) 来配置证书。MsQuic 默认包含的所有密码套件都被认为是安全的，但必须正确设置 MsQuic 在客户端和服务器上验证证书的方式，才能确保建立起安全且经过身份认证的通信通道。

在服务器上，为了使用 XSTS 令牌进行客户端身份认证，应指定 `QUIC_CREDENTIAL_FLAG_REQUIRE_CLIENT_AUTHENTICATION`、`QUIC_CREDENTIAL_FLAG_INDICATE_CERTIFICATE_RECEIVED` 和 `QUIC_CREDENTIAL_FLAG_NO_CERTIFICATE_VALIDATION` 标志。指定 `QUIC_CREDENTIAL_FLAG_NO_CERTIFICATE_VALIDATION` 标志后，你必须按 [安全客户端/服务器通信最佳实践 (NDA 主题)](https://learn.microsoft.com/gaming/gdk/docs/gdk-dev/game-principles/security/communication-security/communication-security-impl/gc-secure-game-mesh-impl#ClientAuthentication) 中所述，在 [QUIC\_CONNECTION\_EVENT\_PEER\_CERTIFICATE\_RECEIVED](https://github.com/microsoft/msquic/blob/main/docs/api/QUIC_CONNECTION_EVENT.md#quic_connection_event_peer_certificate_received) 事件回调中自行验证客户端证书。

此外在服务器上，应提供正确根签发的证书，以便让客户端像连接 HTTPS Web 服务器一样对你的服务器进行身份认证。

在客户端，*绝不* 应指定 `QUIC_CREDENTIAL_FLAG_NO_CERTIFICATE_VALIDATION` 标志，因为 MsQuic 默认的服务器身份认证行为是验证身份的最简单也最安全的方式。相反，对于 XSTS 令牌客户端身份认证，应指定 `QUIC_CREDENTIAL_FLAG_CLIENT` 标志，并按 [安全客户端/服务器通信最佳实践 (NDA 主题)](https://learn.microsoft.com/gaming/gdk/docs/gdk-dev/game-principles/security/communication-security/communication-security-impl/gc-secure-game-mesh-impl#ClientAuthentication) 中所述提供由服务器生成的证书。我们建议通过指定 `QUIC_CREDENTIAL_TYPE_CERTIFICATE_CONTEXT` 模式并使用 [CertCreateContext](https://learn.microsoft.com/windows/win32/api/wincrypt/nf-wincrypt-certcreatecontext) 等 API 直接根据 Web 请求响应数据生成上下文来提供客户端证书。

## 网络初始化

MsQuic 不会自动为 GDK 游戏处理 [网络初始化](/build/console-features/networking/initialization-connectivity-networking)。在游戏启动后以及每次恢复后，请先等待网络完成初始化，再通过 [MsQuicOpenVersion](https://github.com/microsoft/msquic/blob/main/docs/api/MsQuicOpenVersion.md) 或 [MsQuicOpen](https://github.com/microsoft/msquic/blob/main/docs/api/MsQuicOpen.md) 初始化 MsQuic。

<a id="SuspendResume" />

## 挂起与恢复

使用 `RegisterAppStateChangeNotification` 注册挂起与恢复事件。在挂起时，关闭所有已打开的流，并关闭 MsQuic。然后在恢复时，先等待网络初始化，然后重新打开 MsQuic。

要在挂起超时前快速关闭所有 MsQuic 流，对每个已打开的流调用 [StreamShutdown](https://github.com/microsoft/msquic/blob/main/docs/api/StreamShutdown.md) 并同时指定 `QUIC_STREAM_SHUTDOWN_FLAG_ABORT` 与 `QUIC_STREAM_SHUTDOWN_FLAG_IMMEDIATE` 标志。此调用会立即触发 `QUIC_STREAM_EVENT_SHUTDOWN_COMPLETE` 事件。此时可以安全地调用 [StreamClose](https://github.com/microsoft/msquic/blob/main/docs/api/StreamClose.md) 关闭流。一旦某个连接的所有流都已关闭，调用 [ConnectionShutdown](https://github.com/microsoft/msquic/blob/main/docs/api/ConnectionShutdown.md)（带 `QUIC_CONNECTION_SHUTDOWN_FLAG_SILENT` 标志），随后调用 [ConnectionClose](https://github.com/microsoft/msquic/blob/main/docs/api/ConnectionClose.md)。关闭所有连接后，对任何尚未关闭的注册和配置调用 [RegistrationClose](https://github.com/microsoft/msquic/blob/main/docs/api/RegistrationClose.md) 和 [ConfigurationClose](https://github.com/microsoft/msquic/blob/main/docs/api/ConfigurationClose.md)，最后调用 [MsQuicClose](https://github.com/microsoft/msquic/blob/main/docs/api/MsQuicClose.md)。

## 首选端口

在 GDK 游戏中，请对主要游戏流量使用 [首选本地 UDP 多人游戏端口](/build/console-features/networking/game-mesh/preferred-local-udp-multiplayer-port-networking)。在 MsQuic 中通过在调用 [ConnectionStart](https://github.com/microsoft/msquic/blob/main/docs/api/ConnectionStart.md) 之前，使用 [SetParam](https://github.com/microsoft/msquic/blob/main/docs/api/SetParam.md) 函数在连接对象句柄上设置 `QUIC_PARAM_CONN_LOCAL_ADDRESS` 来指定该端口。

在设置 `QUIC_PARAM_CONN_LOCAL_ADDRESS` 时，请指定 `AF_UNSPEC` 地址族以允许 IPv4 与 IPv6 双栈套接字。以下示例展示了当 `MsQuicCallTable` 由 [MsQuicOpen](https://github.com/microsoft/msquic/blob/main/docs/api/MsQuicOpen.md) 返回、`MsQuicConnectionHandle` 由 [ConnectionOpen](https://github.com/microsoft/msquic/blob/main/docs/api/ConnectionOpen.md) 返回时，如何设置首选端口。

```text theme={null}
uint16_t preferredPort;
if (SUCCEEDED(XNetworkingQueryPreferredLocalUdpMultiplayerPort(&preferredPort)))
{
    QUIC_ADDR localAddress = {};
    localAddress.si_family = AF_UNSPEC;
    localAddress.Ipv4.sin_port = htons(preferredPort);

    QUIC_STATUS status = MsQuicCallTable->SetParam(
        MsQuicConnectionHandle,
        QUIC_PARAM_LEVEL_CONNECTION,
        QUIC_PARAM_CONN_LOCAL_ADDRESS,
        sizeof(localAddress),
        &localAddress);
}
```

## 内存注意事项

MsQuic 的高性能实现允许在 GDK 游戏中传输极高的带宽。作为 [WinSock 内存注意事项](/build/console-features/networking/game-mesh/winsock-intro-networking#SocketMemory) 的补充，使用 MsQuic 时请遵循以下最佳实践以尽量减少内核内存消耗：

GDK 游戏应尽量减少回调中的执行时间。MsQuic 并不为协议执行和上行调用（upcall）使用独立线程。因此，回调中的任何显著延迟都会拖慢协议并增加内核所需的内存消耗。任何需要显著时间或工作量的处理必须在游戏自己的线程中完成。

GDK 游戏应高效管理发送缓冲区，以减少内核内存使用。有关详细信息，请参见 [MsQuic 中的发送缓冲](https://github.com/microsoft/msquic/blob/main/docs/Streams.md#send-buffering)，了解 MsQuic 如何让游戏控制该行为。

强烈建议在使用 MsQuic 时使用异步接收，以确保任何已接收数据都能被高效地传输到用户态缓冲区。[MsQuic 中的接收](https://github.com/microsoft/msquic/blob/main/docs/Streams.md#receiving) 提供了处理异步接收的更多细节。此外，为最大限度减少内核内存消耗，请不要在 MsQuic GDK 客户端中使用部分数据接受特性。

## 另请参阅

[MsQuic](https://github.com/microsoft/msquic)

[MsQuic API 文档](https://github.com/microsoft/msquic/blob/main/docs/API.md)

[MsQuic 发行版本](https://github.com/microsoft/msquic/blob/main/docs/Release.md)

[MsQuic 构建文档](https://github.com/microsoft/msquic/blob/main/docs/BUILD.md)

[MsQuic Echo PlayFab 服务器示例](https://github.com/microsoft/Xbox-GDK-Samples/tree/main/Samples/Live/MsQuicEcho)


## Related topics

- [XBOX 游戏的 Game mesh 网络](/zh-CN/build/console-features/networking/game-mesh/index.md)
- [使用 GDK 在 XBOX 主机上进行网络开发](/zh-CN/build/console-features/networking/index.md)
- [Game Mesh](/zh-CN/build/console-features/networking/game-mesh/game-mesh-toc.md)
- [Microsoft 游戏开发工具包网络简介](/zh-CN/build/console-features/networking/introduction-networking.md)
- [动态电源状态(DPS)](/zh-CN/build/game-principles/sustainability/dynamic-power-states.md)
