xCurl 库——libCurl API 的 Microsoft 游戏开发工具包 (GDK) 兼容实现。xCurl 通过自动遵循所有安全要求与最佳实践简化了游戏开发,无需游戏做任何特殊的逻辑或处理。但它不支持 WebSocket 通信。如果需要实现 WebSocket 通信,请改用 libHttpClient。
xCurl 与 libCurl 的区别在于:xCurl 是构建在 WinHttp 之上的,并且自动遵循 Microsoft 游戏开发工具包 (GDK) 的要求与最佳实践,包括进程生命周期管理 (PLM)。虽然 xCurl 与 libCurl API 兼容,但其内部的传输层完全使用 WinHttp,并未使用 libCurl。因此 xCurl 无需与 libCurl 开源实现保持同步,包括 bug 修复、版本号等。开发者可通过 xCurl 在所有平台上保留同一份 libCurl HTTP 实现,只需更改一个头文件的包含和库的链接。
xCurl 未实现若干 libCurl API,原因是它们要么在游戏开发场景中不常用,要么在 WinHttp 中没有可映射的等价功能。稍后本文将说明具体差异。
xCurl 依赖 Gaming Runtime,在 XGameRuntimeInitialize 被调用之前无法初始化。
要了解 xCurl 方法的工作原理,请参阅 libCurl API 文档。
xCurl 与 WinHttp 实现在 Windows PC 和 XBOX 主机上无需修改代码即可工作。开发者支持
xCurl 由 WinHttp 提供支持,而非 libCurl,并且是 Microsoft 游戏开发工具包 (GDK) 的一部分。
支持请求应通过 Microsoft 游戏开发工具包 (GDK) 游戏推荐的支持渠道提交,例如联系你的 Microsoft 代表,或通过 XBOX 开发者论坛联系开发者支持团队。
将 xCurl 添加到项目
要在 Windows 10 PC 或 XBOX 主机上的 Microsoft 游戏开发工具包 (GDK) 游戏中使用xCurl,请在项目中引入 xCurl 扩展 SDK 的头文件与库。
- 确保已在开发 PC 上安装 Gaming Runtime Development Kit (GRDK)。
- 打开游戏的 .vcxproj 文件,然后添加以下元素。这样会链接导入库并将 xCurl.dll 包含在构建输出中。
xCurl使用了不同的头文件以区别于libCurl。将游戏中原本包含 curl.h 的位置替换为 xCurl.h,如下所示。
配置
xCurl 等价于使用以下构建标志编译的 libCurl。
- HTTP_ONLY
- CURL_NO_OLDIES
- CURL_DISABLE_PROXY
- CURL_DISABLE_COOKIES
- CURL_DISABLE_DOH
- CURL_DISABLE_PROGRESS_METER
- CURL_DISABLE_MIME
- USE_SCHANNEL
网络初始化
xCurl 自动处理网络初始化。你可以在游戏生命周期的任何时点设置并发起请求。在网络初始化完成之前启动的任何请求都会被延迟并排队,等待网络初始化完成后再执行。xCurl 会确保你的请求在最早的时机发出,游戏无需额外处理。
游戏挂起/恢复
xCurl 自动处理挂起与恢复。挂起时,所有未完成请求会立即取消,并以 CURLE_NO_CONNECTION_AVAILABLE 失败。此外,对这些请求调用 curl_easy_getinfo 查询 CURLINFO_OS_ERRNO 会返回 HRESULT_FROM_WIN32(PROCESS_SUSPEND_RESUME),与其他 GRTS API 一致,便于你在需要时把这类失败与普通网络断开失败区分处理。
在整个游戏生命周期中,所有 xCurl 句柄始终有效,包括跨挂起/恢复边界。挂起/恢复时无需清理或重新初始化任何 xCurl 句柄。挂起后启动的任何新请求都会延迟到恢复及随后网络初始化之后再进行。这种延迟确保它们会尽快启动,无需游戏做任何额外处理。
当你的游戏对
xCurl 使用 multi 接口时,即使处于挂起状态,只要还有未完成请求,游戏也应继续调用 curl_multi_perform,可选地同时调用 curl_multi_poll 或 curl_multi_wait。xCurl 会阻塞挂起直到所有进行中的请求完成;如果不调用 curl_multi_perform,可能导致游戏在挂起期间超时。我们建议在整个生命周期中持续调用 curl_multi_perform,不必区分挂起/恢复状态。xCurl 会在内部处理挂起状态的所有细节。安全功能
通过xCurl 发起的所有 HTTPS 请求都遵循 通信安全最佳实践 (NDA 文章)。xCurl 会自动执行你在游戏“单点登录门户”中指定的任何特殊证书固定 (certificate pinning)。不支持使用 CURLOPT_SSL_VERIFYPEER 禁用证书校验。
在开发套件上,出于调试与测试目的可以指定未加密的 HTTP 方案 http://。所有 RETAIL 请求必须指定 HTTPS 方案 https:// 以提供推荐级别的保护。对于未显式指定方案的 xCurl 请求,会推断为 HTTPS 方案。
xCurl 不会自动插入令牌。要获取 XBOX Live 令牌,你的游戏应调用 GRTS API XUserGetTokenAndSignatureAsync 或 XUserGetTokenAndSignatureUtf16Async 获取授权和签名标头,然后在发起请求之前通过对 curl_easy_setopt 使用 CURLOPT_HEADER、CURLOPT_HTTPHEADER 或 CURLOPT_HEADERFUNCTION 选项来设置标头。内存与并发注意事项
xCurl 与 WinHttp 共享相同的并发请求限制。游戏应将并发请求数控制在 8 个或以下,以确保所有调用能正常工作。此并发限制适用于来自 xCurl、WinHttp 和 XBOX 服务 API 的所有并发请求。
xCurl 使用翻转缓冲区 (flip buffer) 接收数据。该模式可在游戏读取一个缓冲区的同时填充另一个缓冲区,从而提供更高吞吐量。但如果读回调耗时太长,或在 multi 模式下 curl_multi_perform 调用不够频繁,WinSock 内核内存可能会累积。有关 WinSock 内核内存的更多信息,请参阅 套接字内存注意事项。
控制 xCurl 分配
默认情况下,xCurl 使用 Windows 堆,可通过 XMemSetWin32HeapTrackingHooks 跟踪其分配。或者,也可以像 libCurl 那样在初始化时提供内存函数。
除了 curl_global_init_mem,xCurl 还提供了可选的 xCurl_global_init_mem。提供给此版本 init 的回调与其他 Microsoft 游戏开发工具包 (GDK) 内存回调类似,并提供了比标准 libCurl 回调更多的被分配数据的信息。
支持的选项
xCurl 中 easy 句柄支持以下选项。
- CURLOPT_VERBOSE
- CURLOPT_HEADER
- CURLOPT_NOBODY
- CURLOPT_FAILONERROR
- CURLOPT_UPLOAD
- CURLOPT_PUT
- CURLOPT_ACCEPT_ENCODING
- CURLOPT_TRANSFER_ENCODING
- CURLOPT_FOLLOWLOCATION
- CURLOPT_MAXREDIRS
- CURLOPT_POST
- CURLOPT_COPYPOSTFIELDS
- CURLOPT_POSTFIELDS
- CURLOPT_POSTFIELDSIZE
- CURLOPT_POSTFIELDSIZE_LARGE
- CURLOPT_POSTREDIR
- CURLOPT_REFERER
- CURLOPT_USERAGENT
- CURLOPT_HTTPHEADER
- CURLOPT_HTTPGET
- CURLOPT_HTTP_VERSION
- CURLOPT_CUSTOMREQUEST
- CURLOPT_HEADERDATA
- CURLOPT_ERRORBUFFER
- CURLOPT_WRITEDATA
- CURLOPT_READDATA
- CURLOPT_INFILESIZE
- CURLOPT_INFILESIZE_LARGE
- CURLOPT_CURLU
- CURLOPT_URL
- CURLOPT_PORT
- CURLOPT_TIMEOUT
- CURLOPT_TIMEOUT_MS
- CURLOPT_CONNECTTIMEOUT
- CURLOPT_CONNECTTIMEOUT_MS
- CURLOPT_DEBUGFUNCTION
- CURLOPT_DEBUGDATA
- CURLOPT_HEADERFUNCTION
- CURLOPT_WRITEFUNCTION
- CURLOPT_READFUNCTION
- CURLOPT_SSL_VERIFYPEER
- CURLOPT_SSL_VERIFYHOST
- CURLOPT_SSLCERT
- CURLOPT_BUFFERSIZE
- CURLOPT_UPLOAD_BUFFERSIZE
- CURLOPT_PRIVATE
- CURLOPT_IGNORE_CONTENT_LENGTH
- CURLOPT_HTTP_TRANSFER_DECODING
- CURLOPT_HTTP_CONTENT_DECODING
不支持的功能
Sockets 与 fd_set
xCurl 不暴露用于传输的底层套接字。因此,xCurl 未实现用于套接字操作的任何选项和 API。这也使得无法使用 fd_sets 通过 select 与 poll 等待数据到来。要等待工作到来,请使用 curl_multi_wait 和 curl_multi_poll。
xCurl 中不存在以下 API:
curl_easy_sendcurl_easy_recvcurl_multi_socketcurl_multi_socket_actioncurl_multi_socket_allcurl_multi_assigncurl_multi_fdset
CURLE_NOT_BUILT_IN 错误:
- CURLOPT_LOCALPORT
- CURLOPT_CONNECT_ONLY
- CURLOPT_SOCKOPTFUNCTION
- CURLOPT_SOCKOPTDATA
- CURLOPT_OPENSOCKETFUNCTION
- CURLOPT_OPENSOCKETDATA
- CURLOPT_CLOSESOCKETFUNCTION
- CURLOPT_CLOSESOCKETDATA
- CURLOPT_XOAUTH2_BEARER
- CURLOPT_PROGRESSFUNCTION
- CURLOPT_PROGRESSDATA
- CURLOPT_XFERINFOFUNCTION
- CURLOPT_XFERINFODATA
- CURLOPT_NOPROGRESS
- CURLINFO_LASTSOCKET
- CURLINFO_ACTIVESOCKET
- CURLMOPT_SOCKETFUNCTION
- CURLMOPT_SOCKETDATA
- CURLMOPT_PIPELINING
- CURLMOPT_PUSHFUNCTION
CURL Share
CURL 的 Share 接口未实现。
