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_AUTHENTICATION
、 QUIC_CREDENTIAL_FLAG_INDICATE_CERTIFICATE_RECEIVED
和 QUIC_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) 游戏的网络初始化。 在启动游戏后和每次恢复后等待网络初始化,然后再使用MsQuicOpenVersion或MsQuicOpen 初始化 MsQuicOpen。
暂停和继续
必须通过 RegisterAppStateChangeNotification
注册暂停和继续事件。 暂停时,应关闭任何打开的流,然后关闭 MsQuic。 然后,当恢复时,应等待网络初始化,然后重新打开 MsQuic。
若要在暂停超时内快速关闭所有 MsQuic 流,应首先使用QUIC_STREAM_SHUTDOWN_FLAG_ABORT
和QUIC_STREAM_SHUTDOWN_FLAG_IMMEDIATE
标志对每个打开的流调用StreamShutdown。 这将立即触发 QUIC_STREAM_EVENT_SHUTDOWN_COMPLETE
事件,此时可以安全地调用StreamClose来关闭流。 给定连接的所有流关闭后,应使用QUIC_CONNECTION_SHUTDOWN_FLAG_SILENT
标志,后跟ConnectionClose调用ConnectionShutdown。 关闭所有连接后,应调用RegistrationClose和ConfigurationClose以获取任何未完成的注册和配置,后跟MsQuicClose。
首选端口
建议 Microsoft 游戏开发工具包 (GDK) 游戏将 首选的本地 UDP 多人游戏端口 用于主游戏流量。 在调用ConnectionStart之前,可以通过SetParam函数在 MsQuic 中使用连接对象句柄上的QUIC_PARAM_CONN_LOCAL_ADDRESS
设置此端口。
设置 QUIC_PARAM_CONN_LOCAL_ADDRESS
时,建议指定 AF_UNSPEC
系列以允许双堆栈 IPv4 和 IPv6 套接字。 下面是一个示例,说明如何设置给定端口的首选端口, MsQuicCallTable
从 MsQuicOpen 返回, MsQuicConnectionHandle
从 ConnectionOpen返回。
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 客户端中使用部分数据接受功能,以最大程度地减少内核内存消耗量。