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

# 多人游戏会话目录概述

> MPSD 服务、XblMultiplayer 会话句柄、更改通知以及跨 XBOX Live 客户端和游戏的会话同步的概述。

<a id="top" />

本主题介绍多人游戏会话目录 (MPSD) 服务如何让游戏共享连接一组用户所需的基本信息。

MPSD 在发送和接受邀请时,以及在通过玩家卡加入用户时,与外壳和主机操作系统协调。

MPSD 在多个客户端间集中管理游戏的多人游戏系统元数据。
MPSD 确保会话功能同步且一致。

MPSD 是在 XBOX services 云中运行的服务。
它由 `XblMultiplayer` 函数封装。

本主题涵盖以下内容:

* [MPSD 会话](#mpsd-sessions)
* [MPSD 更改通知处理和断开连接检测](#mpsd-change-notification-handling-and-disconnect-detection)
* [MPSD 会话句柄](#mpsd-handles-to-sessions)
* [会话更新的同步](#synchronization-of-session-updates)
* [调用 MPSD](#calling-mpsd)
* [多人游戏会话浏览器](#multiplayer-session-explorer)

<a id="mpsd-sessions" />

## MPSD 会话

MPSD 会话由其 `XblMultiplayerSessionHandle` 标识,表示一个或多个用户玩游戏的场景。
会话由 MPSD 存储为 XBOX services 云中的安全 JSON 文档。

具体而言,MPSD 会话具有以下特征。

* 它由游戏创建和管理。
* 它具有唯一的 URI。有关详细信息,请参阅[会话目录 URI](/reference/live/rest/uri/sessiondirectory/atoc-reference-sessiondirectory)。
* 它支持用户(称为会话成员)之间的连接。
* 它存储支持游戏玩法的数据,如每个成员的属性、游戏设置、引导信息和游戏服务器信息。

每个会话都包含玩家的 XBOX 用户标识符 (XUID) 和安全设备关联地址数据。

MPSD 支持多种类型的会话来设置各种多人游戏,包括以下几种。

| 会话变种 | 说明                                                                                                                                      |
| ---- | --------------------------------------------------------------------------------------------------------------------------------------- |
| 游戏会话 | 游戏玩法的模式。游戏会话可以是对等、点对主机、点对服务器或这些类型的混合。                                                                                                   |
| 票证会话 | 在对战匹配期间用于跟踪匹配状态的辅助会话。它通常也是大厅会话,有时可能是游戏会话。有关详细信息,请参阅[对战匹配概述](/services/xbox-services/multiplayer/matchmaking/live-matchmaking-overview)。 |
| 目标会话 | 在对战匹配期间创建的辅助会话,用于表示匹配的游戏玩法。它几乎总是也是游戏会话。有关详细信息,请参阅[对战匹配概述](/services/xbox-services/multiplayer/matchmaking/live-matchmaking-overview)。   |
| 大厅会话 | 用于容纳等待加入游戏会话的已受邀玩家的辅助会话。许多游戏同时创建大厅会话和游戏会话。                                                                                              |

[返回本主题顶部。](#top)

<a id="mpsd-change-notification-handling-and-disconnect-detection" />

## MPSD 更改通知处理和断开连接检测

客户端使用实时活动 (RTA) 服务 Web 套接字连接到 MPSD。

该连接用于执行以下操作:

* 基于游戏发起的事件订阅,在会话更改发生时发送简短通知(shoulder tap)。
* 检测用户断开连接。
* 根据断开连接检测,将用户设置为非活动,然后将其从会话中删除。

### 建立用户连接

XBOX Services API (XSAPI) 库管理客户端和 MPSD 之间的连接。

1. 游戏调用 [XblMultiplayerSetSubscriptionsEnabled](/reference/live/xsapi-c/multiplayer_c/functions/xblmultiplayersetsubscriptionsenabled)。此方法告知 XSAPI 客户端打算将 RTA 连接用于多人游戏目的。

2. 当游戏首次调用 [XblMultiplayerWriteSessionAsync](/reference/live/xsapi-c/multiplayer_c/functions/xblmultiplayerwritesessionasync) 或 [XblMultiplayerWriteSessionByHandleAsync](/reference/live/xsapi-c/multiplayer_c/functions/xblmultiplayerwritesessionbyhandleasync),将当前用户设置为活动状态时,将创建连接并挂接到 MPSD。

<Note>若要启用会话通知并检测断开连接,会话模板必须将 `connectionRequiredForActiveMembers` 设置为 `true`。</Note>

### 订阅会话更改

MPSD 使用 shoulder tap 作为轻量级通知,以指示感兴趣的内容已更改。
启用订阅后,游戏可以通过调用 [XblMultiplayerSessionSetSessionChangeSubscription](/reference/live/xsapi-c/multiplayer_c/functions/xblmultiplayersessionsetsessionchangesubscription) 订阅会话更改的 shoulder tap。

有关详细信息,请参阅"多人游戏任务"主题中的[订阅 MPSD 会话更改通知](/services/xbox-services/multiplayer/mpsd/how-to/live-mpsd-how-tos#sfmscn)一节。

### 处理 shoulder tap

当会话的更改与游戏对该会话的订阅相匹配时,MPSD 会使用 [XblMultiplayerSessionChangedHandler](/reference/live/xsapi-c/multiplayer_c/functions/xblmultiplayersessionchangedhandler) 处理程序通知游戏此更改。
然后,游戏应检索会话并将检索到的会话版本与先前缓存的视图进行比较,然后采取适当的操作。

### 处理连接状态更改的通知

游戏可以收到与 MPSD 的连接运行状况变化的通知。

两个事件表示这些变化。

* [XblMultiplayerSessionSubscriptionLostHandler](/reference/live/xsapi-c/multiplayer_c/functions/xblmultiplayersessionsubscriptionlosthandler) 处理程序 — 在游戏与 MPSD 的 RTA 服务连接丢失时触发。当此事件发生时,游戏应关闭多人游戏。
* [XblRealTimeActivityConnectionStateChangeHandler](/reference/live/xsapi-c/real_time_activity_c/functions/xblrealtimeactivityconnectionstatechangehandler) 处理程序 — 在游戏与 RTA 服务的连接运行状况发生临时变化时触发。游戏在收到此事件时不需要采取任何操作,但该事件对于诊断目的可能很有用。

### 断开客户端连接

当游戏通过调用 [XblMultiplayerSetSubscriptionsEnabled](/reference/live/xsapi-c/multiplayer_c/functions/xblmultiplayersetsubscriptionsenabled) 禁用通知时,你的游戏客户端会断开与 MPSD 的连接。
在此调用后不久,[XblMultiplayerSessionSubscriptionLostHandler](/reference/live/xsapi-c/multiplayer_c/functions/xblmultiplayersessionsubscriptionlosthandler) 处理程序会触发,指示客户端已断开与 MPSD 的连接。

<Note>在早期的多人游戏版本中,游戏调用 `XblRealTimeActivityDeactivate` 断开与 RTA 服务的连接。
对于 2015 多人游戏服务,此方法无效。
在使用 `false` 值调用 [XblMultiplayerSetSubscriptionsEnabled](/reference/live/xsapi-c/multiplayer_c/functions/xblmultiplayersetsubscriptionsenabled) 后,如果 Web 套接字连接没有用户(例如与 Presence 服务的 RTA 服务订阅),则会自动断开连接。</Note>

### 断开连接检测

MPSD 使用其断开连接检测功能来快速找出用户何时非正常断开连接。
非正常断开连接的原因包括玩家的网络故障或游戏崩溃。

MPSD 将断开连接的玩家的状态从"活动"更改为"非活动",并根据成员对会话的订阅情况,酌情通知其他会话成员此更改。

#### 处理 RTA 重新连接

XSAPI 在断开连接时尝试重新连接到 RTA 并重新提交 RTA 订阅。(有关详细信息,请参阅 [RTA 服务的最佳实践](/services/xbox-services/fundamentals/rta/concepts/live-rta-best-practices)。)重新提交多人游戏 RTA 订阅会更新用于将 MPSD 会话中的用户与客户端 RTA 连接关联的连接 ID。

XSAPI 通过 [XblMultiplayerAddConnectionIdChangedHandler](/reference/live/xsapi-c/multiplayer_c/functions/xblmultiplayeraddconnectionidchangedhandler) 通知游戏 MPSD 连接 ID 已更改。在回调内部,游戏必须将新的连接 ID 写入 MPSD 会话。可以通过调用 [XblMultiplayerSessionCurrentUserSetStatus](/reference/live/xsapi-c/multiplayer_c/functions/xblmultiplayersessioncurrentusersetstatus),然后通过调用 [XblMultiplayerWriteSessionAsync](/reference/live/xsapi-c/multiplayer_c/functions/xblmultiplayerwritesessionasync) 写入会话,将新的连接 ID 写入会话。

```cpp theme={null}
void* context{ nullptr };
XblFunctionContext connectionIdChangedFunctionContext = XblMultiplayerAddConnectionIdChangedHandler(
    xblContextHandle,
    [](void* context) {
        XblMultiplayerSessionHandle sessionHandle; // Retrieve the MPSD session to update
        XblMultiplayerSessionCurrentUserSetStatus(sessionHandle, XblMultiplayerSessionMemberStatus::Active);

        auto asyncBlock = std::make_unique<XAsyncBlock>();
        asyncBlock->queue = queue;
        asyncBlock->context = nullptr;
        asyncBlock->callback = [](XAsyncBlock* asyncBlock)
        {
            std::unique_ptr<XAsyncBlock> asyncBlockPtr{ asyncBlock };

            XblMultiplayerSessionHandle sessionHandle;
            HRESULT hr = XblMultiplayerWriteSessionResult(asyncBlock, &sessionHandle);
            if (SUCCEEDED(hr))
            {
                // If the write call succeeds, the connection ID has been updated and no further action is needed.
            }
            else
            {
                // If the write call fails, it's likely that the user has been removed from the session.
            }
        };

        auto hr = XblMultiplayerWriteSessionAsync(xblContextHandle, sessionHandle, XblMultiplayerSessionWriteMode::UpdateExisting, asyncBlock.get());
        if (SUCCEEDED(hr))
        {
            asyncBlock.release();
        }
    }, 
    context);
```

[返回本主题顶部。](#top)

<a id="mpsd-handles-to-sessions" />

## MPSD 会话句柄

MPSD 会话句柄是对会话的抽象且不可变的引用,还可以包含其他类型化数据。
它类似于文件句柄。
所有句柄都有一个句柄 ID (GUID) 和一个完整的会话引用,该引用由服务配置 ID (SCID)、会话模板和会话名称组成。
句柄无法更新,但可以创建、读取和删除。

<Note>句柄可以指向不存在的会话。
使用不存在的会话名称创建句柄不会导致创建新会话。</Note>

### 句柄类型

2015 多人游戏支持邀请句柄和活动句柄。

#### 邀请句柄

邀请句柄表示对特定用户的邀请。
特定类型的数据包括源用户、目标用户和描述邀请的上下文字符串;例如,特定的游戏模式。

邀请句柄授予对打开会话的读写访问权限。
如果会话关闭,则句柄授予只读会话访问权限。

<Note>即使会话已满或已关闭,MPSD 也可以创建邀请。</Note>

### 创建邀请句柄

若要创建邀请句柄,游戏调用 [XblMultiplayerSendInvitesAsync](/reference/live/xsapi-c/multiplayer_c/functions/xblmultiplayersendinvitesasync)。
此方法在通知中向指定用户发送邀请,收件人可以采取措施接受邀请。

### 创建活动句柄

若要创建活动句柄,游戏调用 [XblMultiplayerSetActivityAsync](/reference/live/xsapi-c/multiplayer_c/functions/xblmultiplayersetactivityasync)。
MPSD 将新的句柄 ID 设置为会话成员的绑定活动。

如果先前有绑定活动,MPSD 会删除相应的句柄。
当活动成员变为非活动或离开会话时,MPSD 会删除绑定的活动句柄。

### 使用句柄

当用户接受邀请(邀请句柄)以及用户加入好友的当前活动(活动句柄)时,游戏将使用句柄。

在这两种情况下,游戏必须执行以下操作。

1. 从游戏激活参数获取句柄 ID。
2. 创建本地 MPSD 会话对象,然后以活动状态加入。
3. 写入会话,传入相应的句柄。

[返回本主题顶部。](#top)

<a id="synchronization-of-session-updates" />

## 会话更新的同步

会话是一种共享资源,可以由其任何成员创建或更新。因此,可能会发生冲突的写入。
例如,如果一个游戏覆盖另一个游戏所做的更改,则可能导致意外结果。
MPSD 解决这些冲突的方法是支持乐观并发和读取-修改-写入模式。

MPSD 对会话更新的同步使用了两种相关的高级实现模式。

* 由仲裁者更新会话的共享部分。如果你的实现涉及单个仲裁者,则可以避免对大多数写入操作使用同步更新。游戏可以避免对以下情况进行同步。

  * 仲裁者对会话共享部分所做的任何更新,除非它们与传达仲裁者的身份有关

  * 游戏对会话内成员区域所做的任何更新

  > \[!NOTE]
  > 尽管前面提到的更新类型不需要同步,但同步对 [XblMultiplayerSessionProperties](/reference/live/xsapi-c/multiplayer_c/structs/xblmultiplayersessionproperties)`::HostDeviceToken` 属性的任何更新仍很重要。
  > 此属性用于传达仲裁者的身份,例如作为仲裁者迁移的一部分。

* 所有客户端都更新会话的共享部分。在这种情况下,对会话共享部分的所有更新都必须同步。但是,游戏仍然可以在不同步的情况下写入自己的成员区域。

### 使用多人游戏 API 更新会话同步

以下多人游戏 API 方法实现乐观并发。

* [XblMultiplayerWriteSessionAsync](/reference/live/xsapi-c/multiplayer_c/functions/xblmultiplayerwritesessionasync)
* [XblMultiplayerWriteSessionByHandleAsync](/reference/live/xsapi-c/multiplayer_c/functions/xblmultiplayerwritesessionbyhandleasync)

每个写入方法都接受一个 [XblMultiplayerSessionWriteMode](/reference/live/xsapi-c/multiplayer_c/enums/xblmultiplayersessionwritemode) 值。
传递 `SynchronizedUpdate` 值将对更新使用乐观并发。

枚举中的其他值可帮助解决会话初始创建时的潜在冲突。
对 MPSD 会话中可能被其他游戏写入的部分进行的任何写入都必须使用同步更新。
但是,并非所有写入都必须受到保护。

如果你的游戏尝试使用其中一种写入会话方法将本地会话对象写入 MPSD,则可能会收到 HTTP/412 状态代码。在这种情况下,应通过发出 [XblMultiplayerGetSessionAsync](/reference/live/xsapi-c/multiplayer_c/functions/xblmultiplayergetsessionasync) 调用来刷新本地副本,以获取会话的最新服务器版本,然后再尝试写入。
否则,本地会话文档将继续包含错误数据,写入会话的调用将继续失败。

<Note>当游戏调用其中一种写入会话方法时,可能会返回会话的更新版本。
如果返回会话的更新版本,游戏应以线程安全的方式将其本地缓存副本替换为新版本。</Note>

### 使用多人游戏 REST API 更新会话同步

MPSD 通过使用带有 ETag 设置的 HTTP "if-match" 标头和读取-修改-写入模式,通过 REST 功能支持会话更新中的乐观并发。
在写入请求中传递的 ETag 应该是 MPSD 在上一次读取请求中返回的 ETag。

[返回本主题顶部。](#top)

<a id="calling-mpsd" />

## 调用 MPSD

游戏可以通过以下方式访问 MPSD 以使用多人游戏系统和对战匹配。

* 我们建议你使用多人游戏 API,其中包含充当 RESTful 功能包装器的类。有关详细信息,请参阅 `XblMultiplayer` 前缀函数。对于 SmartMatch 对战匹配,请使用由 `XblMatchmaking` 前缀函数表示的对战匹配 API。
* 使用对包含在 [XBOX services RESTful 参考](/reference/live/rest/atoc-xboxlivews-reference)中的多人游戏和对战匹配 REST API 的直接标准 HTTP 调用。适用的 URI 在"会话目录 URI"(用于多人游戏)和"对战匹配 URI"(用于对战匹配)部分进行了描述。相关的 JSON 对象在 JavaScript 对象表示法 (JSON) 对象引用部分描述。

### 使用多人游戏 API 调用 MPSD

我们建议使用 XSAPI 中的多人游戏和对战匹配 API 调用 MPSD。

<Note>示例是使用多人游戏和对战匹配 API 以及 XSAPI 的其他元素编写的。</Note>

对基础 REST 功能使用包装器代码,可以使用更传统的方法来使用客户端 API 方法,而无需为每个调用处理 HTTP 流量。

### 使用多人游戏 REST API 与 MPSD 交互

游戏或其服务可以使用对多人游戏 REST API 和对战匹配 REST API 的标准 HTTP 调用。
直接使用 REST 功能时,调用方会针对会话目录 URI 发出 `DELETE`、`PUT`、`POST` 和 `GET` 调用以执行大多数操作。
在 `PUT` 请求中,请求正文将合并到现有会话中。

如果没有现有会话,则使用请求正文以及存储在[合作伙伴中心](https://partner.microsoft.com/dashboard)上的会话模板创建新会话。

所有字段都是可选的,只需要指定增量。
因此,`{}` 是零增量的有效 `PUT` 请求。

若要执行假设的 `PUT` 请求,该请求返回合并结果而不影响服务器的会话官方副本,可以将查询字符串 `?nocommit=true` 附加到 `PUT` 请求。

多人游戏和对战匹配 REST API 方法的请求和响应是 JSON 文档。
有关多人游戏会话请求结构,请参阅 [MultiplayerSessionRequest (JSON)](/reference/live/rest/json/json-multiplayersessionrequest)。

关联的响应结构在 [MultiplayerSession (JSON)](/reference/live/rest/json/json-multiplayersession) 中显示。
响应结构将会话成员作为链表,并填充会话及其成员的其他只读属性。

### 查询会话和会话模板 (REST)

游戏可以查询服务配置和会话模板级别的会话信息。
本节介绍使用多人游戏 REST API 的查询。

#### 查询基本会话信息

可以使用会话目录和对战匹配 URI 设置基本会话信息的查询。
查询的结果是会话引用的 JSON 数组,其中包含内联的一些会话数据。
默认情况下,查询最多检索 100 个非私有会话。

<Note>每个查询都必须包含关键字筛选器、XUID 筛选器或两者。</Note>

#### 查询会话模板

若要检索 SCID 的会话模板列表以及特定会话模板的详细信息,请对以下 URI 之一使用 `GET` 方法。

* /serviceconfigs/{scid}/sessiontemplates
* /serviceconfigs/{scid}/sessiontemplates/{sessionTemplateName}

#### 查询会话状态

若要查询会话状态,请对以下 URI 之一使用 `GET` 方法。

* /serviceconfigs/{scid}/sessions
* /serviceconfigs/{scid}/sessiontemplates/{sessionTemplateName}/sessions

[返回本主题顶部。](#top)

<a id="multiplayer-session-explorer" />

## 多人游戏会话浏览器

多人游戏会话浏览器是内置于 MPSD 中的一个工具,用于浏览会话、会话模板和本地化字符串。
该工具仅供开发沙盒使用。

### 访问多人游戏会话浏览器

<Note>若要使用该工具,必须登录。你的浏览仅限于将登录用户作为成员的会话。</Note>

若要访问多人游戏会话浏览器,请在你的 XBOX One(或更高版本)主机上打开浏览器,按下 **View** 按钮,然后在 **Address** 框中输入 \*[https://sessiondirectory.xboxlive.com/debug\*。](https://sessiondirectory.xboxlive.com/debug*。)

<Note>如果你尝试在 RETAIL 沙盒中访问该工具,将收到 HTTP/404 状态代码。有关此代码的详细信息,请参阅[多人游戏会话状态代码](/services/xbox-services/multiplayer/mpsd/how-to/live-mpsd-status-codes)。</Note>

### 打开主页

1. 打开该工具的主页。它显示安全上下文(登录用户和沙盒)以及沙盒中 SCID 的列表。

2. 按下 **Menu** 按钮将此页面固定到主页,这样就不必重新输入 URI。

#### 显示可用会话和模板

1. 在工具中选择一个 SCID 以显示该 SCID 中将登录用户作为成员的会话列表。

2. 在同一页面上,可以选择该 SCID 并显示该 SCID 服务配置中的会话模板和本地化字符串。这些项目通过[合作伙伴中心](https://partner.microsoft.com/dashboard)引入。

### 显示会话的全部内容

在多人游戏会话浏览器中,选择会话名称以显示相应会话的全部内容。

MPSD 显示的会话可能与对会话 URI 的标准 `GET` 方法的响应不同,原因如下。

* GET 调用可能使用 X-Xbl-Contract-Version 标头中较旧的协定版本。多人游戏会话浏览器始终使用最新的协定版本显示会话。

* 通过 `GET` 正常请求会话时,可以触发转换和副作用,如已过期的超时。多人游戏会话浏览器显示会话的存储快照,而不执行任何逻辑、转换或副作用。

* `nextTimer` JSON 对象字段在 MPSD 会话中不存在,因为它与副作用同时计算。

[返回本主题顶部。](#top)

<a id="see-also" />

## 另请参阅

* "多人游戏会话高级主题"主题中的[会话概述](/services/xbox-services/multiplayer/mpsd/concepts/live-mpsd-details#session-overview)一节
* [多人游戏会话状态代码](/services/xbox-services/multiplayer/mpsd/how-to/live-mpsd-status-codes)
* "多人游戏任务"主题中的[更新 MPSD 会话](/services/xbox-services/multiplayer/mpsd/how-to/live-mpsd-how-tos#update-an-mpsd-session)一节
* "多人游戏任务"主题中的[从游戏激活加入 MPSD 会话](/services/xbox-services/multiplayer/mpsd/how-to/live-mpsd-how-tos#jamsfata)一节
* "多人游戏任务"主题中的[订阅 MPSD 会话更改通知](/services/xbox-services/multiplayer/mpsd/how-to/live-mpsd-how-tos#sfmscn)一节
* [对战匹配概述](/services/xbox-services/multiplayer/matchmaking/live-matchmaking-overview)

[返回本主题顶部。](#top)


## Related topics

- [多人游戏会话目录 (MPSD)](/zh-CN/services/xbox-services/multiplayer/mpsd/live-mpsd-nav.md)
- [XBOX services 多人游戏概述](/zh-CN/services/xbox-services/multiplayer/overviews/live-multiplayer-intro.md)
- [多人游戏常见问题和故障排除](/zh-CN/services/xbox-services/multiplayer/mpsd/concepts/live-multiplayer-2015-faq.md)
- [服务到服务多人游戏会话管理](/zh-CN/services/xbox-services/fundamentals/s2s-auth-calls/s2s-calls/s2s-call-patterns/live-mpsd-service-to-service.md)
- [多人游戏任务](/zh-CN/services/xbox-services/multiplayer/mpsd/how-to/live-mpsd-how-tos.md)
