MsQuic

本主题介绍如何将 MsQuic 与 Microsoft 游戏开发工具包 (GDK) 配合使用。 MsQuic 是 IETF QUIC 协议的 Microsoft 实现。 它是跨平台用 C 编写,旨在成为常规用途的 QUIC 库。

QUIC 最初旨在替换使用"TLS over TCP"(如 HTTP)的方案,但此后已扩展为一个常规用途的 UDP 数据传输层,适合在单个连接上多路复用不可靠的实时数据报消息和类似的 TCP 可靠流。 这使得它作为客户端/服务器传输层和实时游戏流量数据流的基础,特别具有吸引力。

MsQuic 专为 GDK 游戏量身定制,还适用于许多平台,包括 Windows Server、Linux 桌面和服务器、iOS、Android 和 MacOS。

MsQuic API 文档介绍了许多重要的 MsQuic 概念,并演示如何针对 MsQuic API 图面进行编码。

QUIC 功能

  • 所有数据包都经过加密,并使用 TLS 1.3 进行握手身份验证。
  • 可靠且不可靠的应用程序数据的并行流。
  • 首次往返时交换应用程序数据 (0-RTT)。
  • 改进了拥塞控制和丢失恢复。
  • 在客户端 IP 地址或端口中保留更改。
  • 无状态负载均衡。
  • 可轻松扩展新功能和扩展。

MsQuic 实现

除了针对 GDK 游戏量身定制外,MsQuic 还有一些不同于其他 QUIC 的功能:

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

MsQuic 实现以下 QUIC RFC:

MsQuic 实现以下 QUIC 草稿扩展:

获取 MsQuic

MsQuic 托管在开源 github 存储库中。 应通过位于此处的官方版本之一来获取 MsQuic。 预发行版/1.9 中添加了 Xbox Series X|S 主机支持,但我们建议尽可能为 Microsoft 游戏开发工具包 (GDK) 游戏使用最新的官方版本。

给定版本的预构建 MsQuic 二进制文件可在特定版本的“资源”部分下获得。 特定版本的 MsQuic 的所有版本风格彼此完全兼容。 虽然 MsQuic 还尝试保持其版本的向后兼容性,但请参阅 MsQuic 文档和发行说明,了解不同版本之间的任何兼容性预期。

Microsoft Game Development Kit (GDK).PC

建议将 msquic_windows_x64_Release_openssl 预构建二进制文件用于 Microsoft Game Development Kit (GDK).PC 游戏。

电脑上的 Microsoft 游戏开发工具包 (GDK) 游戏作为原生 x64 Win32 应用程序运行。 应使用为 x64 平台构建的 MsQuic 版本。 在 PC 上,我们建议使用由 OpenSSL 构建的 MsQuic 版本,因为它支持 Microsoft 游戏开发工具包 (GDK) 支持的所有操作系统版本,而 Schannel 只支持 Windows 11 和更高版本的操作系统。

Microsoft Game Development Kit (GDK).Console

建议将 msquic_gamecore_console_x64_Release_schannel 预构建二进制文件用于 Microsoft Game Development Kit (GDK).PC 游戏。

MsQuic 为 Xbox 主机上的 Microsoft 游戏开发工具包 (GDK) 游戏提供了一种特殊的构建风格。 此风格将 MsQuic 限制为 WINAPI_PARTITION_GAMES 下的 API,并使 MsQuic 链接到 XGamePlatform.lib。 若要使用此构建风格,必须安装 2021 年 10 月版本或更高版本中的 XGDK。 MsQuic 在为 Microsoft 游戏开发工具包 (GDK) 主机进行构建时使用 Schannel。

客户端和服务器身份验证

MsQuic 自动使用与 HTTPS Web 请求相同的身份验证,以验证路径和验证您的服务器。 客户端身份验证应遵循安全客户端/服务器通信的最佳实践(NDA 主题)要求授权中概述的最佳实践。

在 MsQuic 的客户端和服务器上,应将 ConfigurationLoadCredential API 与合适的 QUIC_CREDENTIAL_CONFIG 配合使用,以便配置证书。 默认情况下,MsQuic 中包含的所有密码套件都被视为安全套件,但请务必正确设置 MsQuic 在客户端和服务器上验证证书的方式,以确保建立安全且经过身份验证的通信通道。

在服务器上,若要使用 XSTS 令牌客户端身份验证,应指定 QUIC_CREDENTIAL_FLAG_REQUIRE_CLIENT_AUTHENTICATIONQUIC_CREDENTIAL_FLAG_INDICATE_CERTIFICATE_RECEIVEDQUIC_CREDENTIAL_FLAG_NO_CERTIFICATE_VALIDATION 标志。 指定 QUIC_CREDENTIAL_FLAG_NO_CERTIFICATE_VALIDATION 标志时,必须在 QUIC_CONNECTION_EVENT_PEER_CERTIFICATE_RECEIVED 事件回调中自行验证客户端证书,如安全客户端/服务器通信的最佳实践(NDA 主题)要求授权部分所述。

此外,在服务器上,应提供一个根正确的证书,以便客户端能够像在 HTTPS Web 服务器中一样对服务器进行身份验证。

在客户端上, 不应 指定 QUIC_CREDENTIAL_FLAG_NO_CERTIFICATE_VALIDATION 标志,因为服务器身份验证默认 MsQuic 行为是验证标志的最简单、最安全的方式。 相反,对于 XSTS 令牌客户端身份验证,应指定 QUIC_CREDENTIAL_FLAG_CLIENT 标志以及服务器生成的证书,如安全客户端/服务器通信的最佳实践(NDA 主题)要求授权部分所述。 建议通过指定 QUIC_CREDENTIAL_TYPE_CERTIFICATE_CONTEXT 模式并使用 API(如 CertCreateContext) 直接从 Web 请求响应数据生成上下文,提供客户端证书。

网络初始化

MsQuic 不会自动处理 Microsoft 游戏开发工具包 (GDK) 游戏的网络初始化。 在启动游戏后和每次恢复后等待网络初始化,然后再使用MsQuicOpenVersionMsQuicOpen 初始化 MsQuicOpen。

暂停和继续

必须通过 RegisterAppStateChangeNotification 注册暂停和继续事件。 暂停时,应关闭任何打开的流,然后关闭 MsQuic。 然后,当恢复时,应等待网络初始化,然后重新打开 MsQuic。

若要在暂停超时内快速关闭所有 MsQuic 流,应首先使用QUIC_STREAM_SHUTDOWN_FLAG_ABORTQUIC_STREAM_SHUTDOWN_FLAG_IMMEDIATE标志对每个打开的流调用StreamShutdown。 这将立即触发 QUIC_STREAM_EVENT_SHUTDOWN_COMPLETE 事件,此时可以安全地调用StreamClose来关闭流。 给定连接的所有流关闭后,应使用QUIC_CONNECTION_SHUTDOWN_FLAG_SILENT标志,后跟ConnectionClose调用ConnectionShutdown。 关闭所有连接后,应调用RegistrationCloseConfigurationClose以获取任何未完成的注册和配置,后跟MsQuicClose

首选端口

建议 Microsoft 游戏开发工具包 (GDK) 游戏将 首选的本地 UDP 多人游戏端口 用于主游戏流量。 在调用ConnectionStart之前,可以通过SetParam函数在 MsQuic 中使用连接对象句柄上的QUIC_PARAM_CONN_LOCAL_ADDRESS设置此端口。

设置 QUIC_PARAM_CONN_LOCAL_ADDRESS 时,建议指定 AF_UNSPEC 系列以允许双堆栈 IPv4 和 IPv6 套接字。 下面是一个示例,说明如何设置给定端口的首选端口, MsQuicCallTableMsQuicOpen 返回, MsQuicConnectionHandleConnectionOpen返回。

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 的高性能实现允许将高带宽传输到 Microsoft 游戏开发工具包 (GDK) 游戏或从中传输高带宽。 作为 WinSock 内存注意事项的扩展,使用 MsQuic 时,应遵循以下最佳实践,以最大程度地减少内核的内存消耗:

Microsoft 游戏开发工具包 (GDK) 游戏应将回调中的任何执行时间保持在最低限度。 MsQuic 不使用单独的线程执行协议和向上调用应用。 因此,回调中的任何重大延迟都将延迟协议并增加内核所需的内存消耗。 游戏需要的任何重要时间或工作都必须发生在其自己的线程上。

Microsoft 游戏开发工具包 (GDK) 游戏应有效地管理其发送缓冲区,以最大程度地减少内核内存使用量。 有关 MsQuic 如何允许游戏管理此操作的更多详细信息,请参阅 MsQuic 中的发送缓冲

强烈建议将异步接收与 MsQuic 配合使用,以确保将收到的任何数据高效传输到用户模式缓冲区。 MsQuic 中的接收 包含有关如何处理异步接收的其他详细信息。 此外,我们建议不要在 MsQuic GDK 客户端中使用部分数据接受功能,以最大程度地减少内核内存消耗量。

另请参阅

MsQuic

MsQuic API 文档

MsQuic 版本

生成 MsQuic 文档