QUIC 特性
- 所有数据包都被加密,握手使用 TLS 1.3 进行认证。
- 可靠和不可靠应用数据的并行流。
- 首次往返 (0-RTT) 即可交换应用数据。
- 改进的拥塞控制与丢包恢复。
- 客户端 IP 地址或端口变更后仍可保持连接。
- 无状态负载均衡。
- 易于扩展新特性与扩展。
MsQuic 实现
除针对 GDK 游戏进行定制外,MsQuic 相较于其他 QUIC 实现还有以下多项差异化特性:- 针对客户端和服务器进行优化。
- 针对最大吞吐量与最小延迟进行优化。
- 异步 IO。
- 支持接收端缩放 (RSS)。
- 支持 UDP 发送和接收合并。
获取 MsQuic
Microsoft 在一个开源 GitHub 仓库中托管 MsQuic。请通过其官方发行版本获取 MsQuic,在此查看。XBOX Series X|S 主机支持是在 prerelease/1.9 中加入的,不过对于 GDK 游戏,我们建议尽可能使用最新的官方发布版本。 你可以在特定发行版本的 Assets 部分找到该版本的预构建 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。
客户端与服务器身份认证
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 标志后,你必须按 安全客户端/服务器通信最佳实践 (NDA 主题) 中所述,在 QUIC_CONNECTION_EVENT_PEER_CERTIFICATE_RECEIVED 事件回调中自行验证客户端证书。
此外在服务器上,应提供正确根签发的证书,以便让客户端像连接 HTTPS Web 服务器一样对你的服务器进行身份认证。
在客户端,绝不 应指定 QUIC_CREDENTIAL_FLAG_NO_CERTIFICATE_VALIDATION 标志,因为 MsQuic 默认的服务器身份认证行为是验证身份的最简单也最安全的方式。相反,对于 XSTS 令牌客户端身份认证,应指定 QUIC_CREDENTIAL_FLAG_CLIENT 标志,并按 安全客户端/服务器通信最佳实践 (NDA 主题) 中所述提供由服务器生成的证书。我们建议通过指定 QUIC_CREDENTIAL_TYPE_CERTIFICATE_CONTEXT 模式并使用 CertCreateContext 等 API 直接根据 Web 请求响应数据生成上下文来提供客户端证书。
网络初始化
MsQuic 不会自动为 GDK 游戏处理 网络初始化。在游戏启动后以及每次恢复后,请先等待网络完成初始化,再通过 MsQuicOpenVersion 或 MsQuicOpen 初始化 MsQuic。挂起与恢复
使用RegisterAppStateChangeNotification 注册挂起与恢复事件。在挂起时,关闭所有已打开的流,并关闭 MsQuic。然后在恢复时,先等待网络初始化,然后重新打开 MsQuic。
要在挂起超时前快速关闭所有 MsQuic 流,对每个已打开的流调用 StreamShutdown 并同时指定 QUIC_STREAM_SHUTDOWN_FLAG_ABORT 与 QUIC_STREAM_SHUTDOWN_FLAG_IMMEDIATE 标志。此调用会立即触发 QUIC_STREAM_EVENT_SHUTDOWN_COMPLETE 事件。此时可以安全地调用 StreamClose 关闭流。一旦某个连接的所有流都已关闭,调用 ConnectionShutdown(带 QUIC_CONNECTION_SHUTDOWN_FLAG_SILENT 标志),随后调用 ConnectionClose。关闭所有连接后,对任何尚未关闭的注册和配置调用 RegistrationClose 和 ConfigurationClose,最后调用 MsQuicClose。
首选端口
在 GDK 游戏中,请对主要游戏流量使用 首选本地 UDP 多人游戏端口。在 MsQuic 中通过在调用 ConnectionStart 之前,使用 SetParam 函数在连接对象句柄上设置QUIC_PARAM_CONN_LOCAL_ADDRESS 来指定该端口。
在设置 QUIC_PARAM_CONN_LOCAL_ADDRESS 时,请指定 AF_UNSPEC 地址族以允许 IPv4 与 IPv6 双栈套接字。以下示例展示了当 MsQuicCallTable 由 MsQuicOpen 返回、MsQuicConnectionHandle 由 ConnectionOpen 返回时,如何设置首选端口。
