> ## 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 会话,涵盖成员属性、功能、大小限制、用户状态、超时、仲裁者和进程生命周期管理。

<a id="top" />

使用本主题了解多人游戏会话中的高级概念。

本主题涵盖以下内容:

* [会话概述](#session-overview)
* [成员属性](#member-properties)
* [会话功能](#session-capabilities)
* [会话大小](#session-size)
* [会话用户状态](#session-user-states)
* [可见性和可加入性](#visibility-and-joinability)
* [会话超时](#session-timeouts)
* [单个主机上的多个登录用户](#multiple-signed-in-users-on-a-single-console)
* [进程生命周期管理](#process-lifecycle-management)
* [清理非活动会话](#cleanup-of-inactive-sessions)
* [会话仲裁者](#session-arbiter)

<a id="session-overview" />

## 会话概述

多人游戏会话目录 (MPSD) 中的*会话*具有会话名称,并被标识为会话模板的实例。
*会话模板*是为会话提供默认设置的 JSON 文档。

会话模板是具有服务配置标识符 (SCID)(一个 GUID)的服务配置的一部分。
会话模板位于[合作伙伴中心](https://partner.microsoft.com/dashboard/windows/overview)上。

*服务配置*是用于引入、管理和安全策略的面向开发者的资源。
通过 MPSD 访问会话时,将根据开发者通过合作伙伴中心设置的访问策略针对服务配置执行主体授权。
当在授权对服务配置的访问后加载会话时,会在会话级别执行辅助访问检查(如会话成员资格验证)。

<Info>通过模板设置的功能无法通过写入 MPSD 进行更改。要更改值,必须创建并提交带有必要更改的新模板。任何未通过模板设置的项目都可以通过写入 MPSD 进行更改。</Info>

### 协定版本号

本主题假设您的模板使用协定版本 107,这是 XBOX One(或更高版本)的当前 MPSD 所使用的版本。

### 会话引用

每个 MPSD 会话都由一个会话引用唯一引用,在多人游戏 API 中由 [XblMultiplayerSessionReference](/reference/live/xsapi-c/multiplayer_c/structs/xblmultiplayersessionreference) 结构表示。
会话引用包含以下字符串值。

* 服务配置标识符 (SCID)
* 会话模板名称
* 会话名称

会话引用映射到用于标识会话的 URI,如下所示。
在以下示例映射中,`authority` 是 sessiondirectory.xboxlive.com。

```HTTP theme={null}
https://{authority}/serviceconfigs/{service-config-id}/sessiontemplates/{session-template-name}/sessions/{session-name}
```

### 会话的元素

每个会话都包含强制执行可变性和安全规则的元素组。它们因会话元素而异,同时包含只读的簿记信息(元数据)。
本节介绍在 JSON 文件中包含的会话元素组(用于配置您的会话),以及您选择的模板的 JSON 文件。

<Note>如果您对 HTTP/REST 实现使用自定义包装器,则您的会话和模板必须定义准确反映实现功能的 JSON 对象。</Note>

每个元素组内都有两个内部对象。

* **系统对象:** 这些对象具有由 MPSD 强制执行和解释的固定架构。它们经过验证并合并。因为 MPSD 定义并知道它们的含义,所以它可以对它们进行操作。有关每个系统对象的完整定义,请参阅 `XblMultiplayerSession` 前缀和会话目录 URI 的参考。

* **自定义对象:** 这些对象是可选的,没有架构。它们用于存储与多人游戏相关的元数据。因为 MPSD 无法解释这些数据,所以不对其进行操作。游戏数据或已保存的信息应存储在标题托管存储 (TMS) 中。有关 TMS 的详细信息,请参阅 [XBOX 服务标题存储概述](/services/xbox-services/storage/title-storage/live-title-storage-overview)。

以下是自定义 JSON 对象的示例。

```JSON theme={null}
    "custom": {
      "myField1": true,
      "myField2": "string",
      "myField3": 5.5,
      "myField4": { "myObject": null },
      "myField5": [ "my", "array" ]
    }
```

#### 会话常量

*会话常量*仅在创建时由创建者或会话模板设置。
`/constants/system` 对象用于为通过 MPSD 得知的多人游戏系统定义常量。
与此对象关联的包装器由 [XblMultiplayerSessionConstants](/reference/live/xsapi-c/multiplayer_c/structs/xblmultiplayersessionconstants) 结构表示。

`/constants/system` 对象可以定义许多项目。它们包括 `capabilities` 对象、`metrics` 对象、`managedInitialization`(模板协定版本 104 或 105)或 `memberInitialization`(协定版本 107)对象、`peerToPeerRequirements` 对象、`peerToHostRequirements` 对象和 `measurementsServerAddresses` 对象。

#### 会话属性

使用 `/properties/system` 对象为 MPSD 定义会话属性。
与此对象关联的包装器是 [XblMultiplayerSessionProperties](/reference/live/xsapi-c/multiplayer_c/structs/xblmultiplayersessionproperties) 结构。
会话属性可由会话成员随时写入。

JSON 格式中的会话属性示例包括 `joinRestriction`、`initializationSucceeded` 和 `matchmaking` 对象。
有关使用此元素组的示例,请参阅[目标会话初始化和 QoS](/services/xbox-services/multiplayer/matchmaking/concepts/live-matchmaking-target-session)。

#### 成员常量

在加入时为每个会话成员设置成员常量。
JSON 对象为 `/members/{index}/constants/system`。
表示会话成员的包装器类是 [XblMultiplayerSessionMember](/reference/live/xsapi-c/multiplayer_c/structs/xblmultiplayersessionmember) 结构。

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

<a id="member-properties" />

## 成员属性

成员属性只能由会话成员写入。
它们在 `/members/{index}/properties/system` 对象中设置,并反映 [XblMultiplayerSessionMember](/reference/live/xsapi-c/multiplayer_c/structs/xblmultiplayersessionmember) 结构的元素。

下面是一个示例。

```JSON theme={null}
    {
      // These flags control the member status and "activeTitle" and are mutually exclusive (it's an error to set both to true).
      // For each, false is the same as not present. The default status is "inactive"; that is, neither present.
      "ready": true,
      "active": false,

      // Base-64 blob, or not present. An empty string is the same as not present.
      "secureDeviceAddress": "ryY=",

      // During member initialization, if any members in the list fail, this member will also fail.
      // Can't be set on large sessions.
      "initializationGroup": [ 5 ],

      // List of the groups I'm in and the encounters I just had.
      // An encounter is a brief interaction with a group. When an encounter is reported, it counts as retroactively joining the group 30 seconds ago and just now leaving.
      // Group names use the session name validation rules (like case-insensitive).
      // On large sessions, groups are used to report who played with whom (rather than just session membership). Members
      // who are active in at least one group together at the same time are counted as playing together.
      // Empty lists are the same as no value specified.
      // The set of encounters is a point-in-time property, so it's immediately consumed and will never appear on a response.
      "groups": [ "team-buzz", "posse.99" ],
      "encounters": [ "CoffeeShop-757093D8-E41F-49D0-BB13-17A49B20C6B9" ],

      // Optional list of role preferences that the player has specified for role-based game modes.
      // All role names have to match across all members in the session. Role weights are
      // defined from 0-100.
      "RolePreference": { "medic": 75, "sniper": 25, "assault": 50, "support": 100 },

      // Quality of Service (QoS) measurements by lowercase device token.
      // Like all fields, "measurements" must be updated as a whole. It should be set once when measurement is complete, not incrementally.
      // Metrics can be omitted if they weren't successfully measured; that is, the peer is unreachable.
      // If a "measurements" object is set, it can't contain an entry for the member's own address.
      "measurements": {
        "e69c43a8": {
          "bandwidthDown": 19342,  // Kilobits per second.
          "bandwidthUp": 944,  // Kilobits per second.
          "custom": { }
        }

      // QoS measurements by game-server connection string. Like all fields, "serverMeasurements" must be updated as a whole, so it should be set once when measurement is complete.
      // If empty, it means that none of the measurements were completed within the "serverMeasurementTimeout".
      "serverMeasurements": {
        "server farm a": {
          "latency": 233  // Milliseconds.
        }
      },

      // Subscriptions for shoulder taps on session changes. The "profile" indicates which session changes to tap and other properties of the registration like the minimum time between taps.
      // The subscription is named with a title-generated GUID that's also sent back with the tap as a context ID.
      // Subscriptions can be added and removed individually, without affecting other subscriptions in the "subscriptions" object.
      // To remove a subscription, set its context ID to null.
      // (Like the "ready" and "active" flags, the "subscriptions" data is copied out and maintained internally, so the normal replace-all rule on system fields doesn't apply to "subscriptions".)
      // Can't be set on large sessions.
      "subscriptions": {
        "961dc162-3a8c-4982-b58b-0347ed086bc9": {
          "profile": "party",  // Or "matchmaking", "initialization", "roster", "queuehost", or "queue".
          "onBehalfOfTitleId": "3948320593",  // Optional decimal title ID of the registered channel. If not set, the title ID is taken from the token.
        },
        "709fef70-4638-4b94-905b-24cb02706eb5": null
      }
    }
```

#### 服务器元素

*服务器*是加入或被邀请加入会话的非用户。
关联的 JSON 对象是 `/servers/{server-name}/constants/system` 和 `/servers/{server-name}/properties/system`。
这些对象只能由服务器写入。

<Note>`/servers/{server-name}/constants/system` 对象目前未被使用。</Note>

### 会话配置

您可以通过以下方式控制会话的配置。

* 使用通过合作伙伴中心引入的会话模板。
* 使用对多人游戏和匹配 API 或 REST API 的调用。您仍必须使用模板,但它不必包含您想要配置的值。请注意,您的标题无法覆盖模板中已设置的常量。

提供一个单独的 JSON 文档来定义会话本身。
此外,您必须实现特定标题所需的任何包装器功能。
JSON 文档的内容和任何包装器代码必须精确地相互反映,并且必须反映最新的模板协定版本。

会话的架构版本由会话版本(主版本)和协议修订版(次版本)决定。
这些版本合并到 X-Xbl-Contract-Version 标头中,格式为“100 \* 主版本 + 次版本”。
例如,一个 v1.7 标题在每个 REST 请求上包含以下标头,假设最新的模板协定版本为 107:X-Xbl-Contract-Version: 107。

<Note>我们建议大多数标题(使用 XBOX 服务 API (XSAPI))使用协定版本 105 和会话模板版本 107。</Note>

### 会话模板

每个会话模板都是一个 JSON 文档,它是服务配置的一部分,定义了正在创建的会话的框架,并为新会话提供常量。
有关详细信息,请参阅[多人游戏会话模板](/services/xbox-services/multiplayer/mpsd/concepts/live-session-templates)。

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

<a id="session-capabilities" />

## 会话功能

*功能*是 MPSD 会话中的常量,用于配置 MPSD 应应用于该会话的行为。
您最常使用合作伙伴中心在会话模板中设置功能。

功能在 `/constants/system/capabilities` 对象中设置。
如果不需要功能,请使用空的 `capabilities` 对象。

<Note>标题几乎从不使用多人游戏 API 或匹配 API 更改或访问会话功能。</Note>

会话功能由 [XblMultiplayerSessionCapabilities](/reference/live/xsapi-c/multiplayer_c/structs/xblmultiplayersessioncapabilities) 结构表示。
它们是指示会话可以支持什么的布尔值。

* 连接性
* 游戏玩法
* 大型大小
* 活动成员需要连接

[XblMultiplayerSessionConstants](/reference/live/xsapi-c/multiplayer_c/structs/xblmultiplayersessionconstants) 结构包含一个 `SessionCapabilities` 成员(类型为 [XblMultiplayerSessionCapabilities](/reference/live/xsapi-c/multiplayer_c/structs/xblmultiplayersessioncapabilities)),用于定义以下与会话功能相关的属性。

* `CapabilitiesConnectivity`
* `CapabilitiesGameplay`
* `CapabilitiesLarge`

<Note>如果标题定义了动态会话功能,则相应的属性将为会话常量设置为 `true`。</Note>

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

<a id="session-size" />

## 会话大小

MPSD 会话的大小由该会话中的成员数决定。

### 最大会话大小

会话的最大大小是它可以容纳的最大会话成员数。
它由 [XblMultiplayerSessionConstants](/reference/live/xsapi-c/multiplayer_c/structs/xblmultiplayersessionconstants)`::MaxMembersInSession` 属性表示。
最大成员大小在 `/constants/system` 对象中设置。

最大会话大小为 1 到 100 个会话成员,如果在创建时未设置,则默认为 100。
如果所需的大小超过 100,则该会话称为“大型”会话,并以特殊方式设置。

#### 断开连接

为会话设置最大大小可能导致在某些断开连接场景中空闲位置显示为已满。
例如,如果玩家因网络或电源故障而断开连接,则延迟不会立即反映在会话中。
使用断开连接检测功能将成员设置为非活动状态。有关详细信息,请参阅“多人游戏会话目录概述”主题中的 [MPSD 更改通知处理和断开连接检测](/services/xbox-services/multiplayer/mpsd/live-mpsd-overview#mpsd-change-notification-handling-and-disconnect-detection)部分。

相比之下,使用心跳检测断开连接的对等网状网络通常在两到三秒内就能感知断开连接,并且可以立即打开玩家位置。
但是,仲裁者无法移除其他成员。

### 大型会话

大型 MPSD 会话最多可以有 1,000 个成员,但它禁用了某些会话功能,例如获取所有成员的列表。
会话大型性由 [XblMultiplayerSessionCapabilities](/reference/live/xsapi-c/multiplayer_c/structs/xblmultiplayersessioncapabilities)`::Large` 属性表示。

此属性设置为 `true` 以指示大型会话。“大型”功能在 `/constants/system/capabilities` 对象中指示。
有关详细信息,请参阅[会话功能](#session-capabilities)。

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

<a id="session-user-states" />

## 会话用户状态

MPSD 将*用户状态*定义为已添加到会话的用户的状态。
可能的用户状态由 [XblMultiplayerSessionStatus](/reference/live/xsapi-c/multiplayer_c/enums/xblmultiplayersessionstatus) 枚举定义。
用户在添加到会话之前也被视为具有“可用”状态。

您可以使用 [XblMultiplayerSessionCurrentUserSetStatus](/reference/live/xsapi-c/multiplayer_c/functions/xblmultiplayersessioncurrentusersetstatus) 更改会话用户状态。
对于 REST,通过在游戏会话 JSON 文档中正确设置 `/members/{index}/properties/system` 进行此更改。

### 已保留用户状态

当仲裁者选择用户填补会话中的一个空闲位置时,用户被置于已保留用户状态。
在此状态下,用户尚未正式接受会话邀请或加入会话以开始与对等方连接。

### 活动用户状态

当用户处于活动状态时,标题已代表用户加入会话,并且用户正在积极参与会话。
只要用户仍在玩游戏,用户就会继续处于此状态。

首次启动标题时,它应检查用户是否已经是任何会话的成员,通常通过检查会话状态。
如果用户是会话成员,则标题可以直接进入游戏,并将任何参与的本地成员设置为活动用户状态。

用户在会话中进行游戏时应保持活动状态。
如果用户通过游戏内 UI 离开会话,则应通过调用 [XblMultiplayerSessionLeave](/reference/live/xsapi-c/multiplayer_c/functions/xblmultiplayersessionleave) 将其从会话中移除。
如果用户只是暂时离开游戏(例如标题受限时),则应在合理的时间内将用户保持在活动状态。

如果用户在标题指定的时间段后未返回,则更改用户状态为非活动状态是适当的。

### 非活动用户状态

在非活动状态下,用户当前未与游戏互动,但仍在会话中保存了一个位置。
换句话说,用户是“非活动的”。

将其设置为非活动用户状态的责任在于用户自己的主机。
仲裁者不能这样做。

将用户置于非活动状态的示例场景包括以下情况:

* 标题接收到暂停事件。

* 用户在标题定义的时间段内一直处于非活动状态(没有输入或控制器响应)。我们建议竞争性多人游戏为两分钟。

* 标题已处于受限模式超过两分钟或标题定义的时间段。此受限模式超时时间是用户可能通过使用相关应用或与标题相关的其他体验而离开标题的预期时间。

* 用户已从会话中不正常地断开连接。有关详细信息,请参阅“多人游戏会话目录概述”主题中的 [MPSD 更改通知处理和断开连接检测](/services/xbox-services/multiplayer/mpsd/live-mpsd-overview#mpsd-change-notification-handling-and-disconnect-detection)部分。

如果标题启动并且特定会话成员的用户状态设置为非活动,则说明标题已被暂停或用户在会话中非活动的时间过长。
因为标题正在再次启动,所以表明用户想要继续他们所属的游戏会话。

如果标题启动时用户的状态为活动,则这种情况可能是由于网络断开连接或另一种场景导致标题在被中断之前无法将用户设置为非活动。
在这两种情况下,您的标题都应尝试将用户与游戏重新连接,并允许其他用户继续游戏或将用户从会话中移除。

### 会话结束时的用户状态

当会话结束时,游戏玩法将终止。
标题必须允许所有用户使用 [XblMultiplayerSessionLeave](/reference/live/xsapi-c/multiplayer_c/functions/xblmultiplayersessionleave) 移除自己。
用户离开会话时,与用户关联的会话活动将自动清除。

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

<a id="visibility-and-joinability" />

## 可见性和可加入性

会话访问在 MPSD 级别由两个设置控制:会话可见性和会话可加入性。
本主题中提出的可见性和可加入性建议适用于最常见的标题场景。
如果可能,标题应遵循这些设置。它们应使用标题内的逻辑来最终且权威地确定新玩家是否被允许进入会话。

### 会话可见性

*会话可见性*由创建会话时设置的常量表示。
它通常在会话模板中定义,并确定哪些类型的用户对会话具有读取和写入访问权限。

会话可见性的可能值由 [XblMultiplayerSearchHandleGetVisibility](/reference/live/xsapi-c/multiplayer_c/functions/xblmultiplayersearchhandlegetvisibility) 定义。
JSON 文件中可见性常量允许的设置为 `open`、`visible` 和 `private`。

#### 推荐的游戏会话可见性:open

开放的游戏会话不需要玩家预留,这简化了邀请过程。

发送邀请后,仲裁者不会在 MPSD 中预留玩家,而只会在本地跟踪被邀请的玩家。
因此,玩家可以立即连接到仲裁者并确定他们是否应加入会话、被拒绝或应等待(如果支持等待玩家)。

仲裁者是最终权威。他们做出响应并指示新成员留在或离开会话。

使用开放的游戏会话可见性要求受邀玩家在做出最终决定之前启动标题并连接到仲裁者。
如果会话已满或邀请被拒绝,您可以向用户显示错误消息。

要建立与仲裁者的连接,需要一个安全设备地址。
[XblMultiplayerSessionProperties](/reference/live/xsapi-c/multiplayer_c/structs/xblmultiplayersessionproperties)`::HostDeviceToken` 属性用于查找哪个会话成员是会话的当前仲裁者,以及受邀玩家应使用哪个安全设备地址进行连接。

### 会话可加入性

*会话可加入性*确定哪些类型的用户可以加入会话。
它可以在会话期间动态设置。

会话可加入性的可能值如下。

* **无(默认):** 对可以加入会话的用户没有限制。
* **本地:** 只有本地用户可以加入会话。
* **已关注:** 只有本地用户和其他会话成员关注的用户才能在没有预留的情况下加入会话。

会话仲裁者可以通过可加入性设置创建私有会话。
将可加入性设置为本地或已关注可限制对会话的访问并将其设为私有。

仲裁者还应跟踪会话可加入性,以便在需要时可以在主机级别拒绝较早的会话邀请。
例如,如果任何受邀玩家在会话已经满之前都未到达以加入会话,仲裁者可以指示正在加入的玩家会话已被锁定,他们需要自动离开会话。

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

<a id="session-timeouts" />

## 会话超时

会话可以通过计时器和其他外部事件进行更改。
*会话超时*定义会话成员可以在特定状态下保持的时间段,超过后会自动将其设置为非活动状态或从会话中移除。
MPSD 还支持超时来管理会话生存期。

<Note>对于模板协定版本 104 或 105,超时设置在 `/constants/system/timeouts` 中或托管初始化对象内进行。对于版本 107 或更高版本,设置在 `/constants/system` 中或托管初始化对象内单独进行。</Note>

当计时器到期时,MPSD 不会自动更新会话并立即通知仲裁者任何更改。
会话和超时状态只会在发送读取或写入请求之前立即更新。
立即更新可确保返回的数据是最新的。

<Note>会话超时不会堆叠。在更新时,针对每个会话成员的状态转换只应用一个。</Note>

### 当前定义的超时

本节介绍 MPSD 当前定义的超时。

* 所有超时均以毫秒为单位指定。
* 允许值为 0,表示立即超时。
* 无值的超时被视为无限。

因为超时具有默认值,所以对于无限超时,您应显式指定 `null`。

#### evaluationTimeout

此超时指示会话成员做出和上传评估决定的时间量。
如果未收到决定,则决定计为失败。
此超时放置在托管初始化对象中。

#### inactiveRemovalTimeout

此超时是为已加入会话但当前未参与游戏的会话成员设置的。
默认情况下,成员会在两小时后从会话中移除。

<Note>对于模板协定版本 104 或 105,此超时被指定为非活动超时。</Note>

在许多情况下,我们建议将非活动超时设置为 0。这会导致任何设置为非活动状态的用户立即从会话中移除,并且相应的位置被清除。
对于大多数竞争性多人游戏,这种行为是可取的,以便如果用户已变为非活动状态或达到非活动状态,可以快速添加新玩家。

对于合作或其他多人设计,您可能希望标题在用户断开连接或一段时间内未参与标题时给予他们更多时间重新连接。
请注意,没有单一的解决方案适用于所有设计场景。

#### joinTimeout

此超时指示用户加入会话必须的毫秒数。
未能加入会话的用户的预留将被移除。
此超时放置在托管初始化对象中。

#### measurementTimeout

此超时指示会话成员上传测量的时间量。
未能上传测量的成员会以“timeout”的失败原因被标记。
此超时放置在托管初始化对象中。

<Note>在匹配期间,强制执行 45 秒的 QoS 测量超时。因此,我们建议您在匹配期间使用小于或等于 30 秒的测量超时。</Note>

#### readyRemovalTimeout

此超时是为已加入会话并试图进入游戏的会话成员设置的。
这通常意味着 shell 已代表标题为用户加入,并且它正在启动。
默认情况下,成员在三分钟后从会话中移除并置于非活动状态。

<Note>对于协定版本 104 或 105,此超时被指定为就绪超时。</Note>

#### reservedRemovalTimeout

此超时是为已由他人添加到会话但尚未加入会话的会话成员设置的。
超时到期后,预留将被删除,成员被视为非活动。
默认值为 30 秒。

<Note>对于协定版本 104 或 105,此超时被指定为已保留超时。</Note>

#### sessionEmptyTimeout

此超时指示会话变空后被删除的毫秒数。
默认值为 0。

<Note>对于协定版本 104 或 105,此超时被指定为 `sessionEmpty` 超时。</Note>

### 会话超时示例

1. 会话由四名玩家启动。

2. 两名玩家 A 和 B 由于电源故障而断开连接。他们在游戏中的状态保持为活动。

3. 其他两名玩家 C 和 D 通过使用 [XblMultiplayerSessionLeave](/reference/live/xsapi-c/multiplayer_c/functions/xblmultiplayersessionleave) 正常退出。

4. 会话仍然打开。玩家 A 和 B 已断开连接,但仍处于活动状态。

5. 几天后,玩家 A 返回并启动游戏。

6. 玩家 A 的游戏检查玩家 A 是其成员的会话(执行读取),并找到几天前的孤立会话。

7. 会话对仍在会话中的两名玩家(A 和 B)进行在线状态检查。
   1. 因为玩家 A 正在运行标题,对玩家 A 的在线状态检查成功。玩家在匹配中的活动状态保持不变。
   2. 玩家 B 未运行标题。因此,对玩家 B 的在线状态检查失败。服务将玩家 B 的状态设置为非活动。此时,玩家 B 的非活动超时开始。

8. 玩家 A 通过使用 [XblMultiplayerSessionLeave](/reference/live/xsapi-c/multiplayer_c/functions/xblmultiplayersessionleave) 方法正常退出会话。

9. 玩家 B 的非活动超时到期,在下次任何人进行的读取或写入时将其从会话中移除。

10. 会话现在有零个成员,并被从服务中移除。

如果示例会话的非活动超时设置为 0,则玩家 B 在步骤 7.1 中的在线状态检查后立即超时,并且可能被会话写入删除。
在这种情况下,会话关闭而无需从会话进行额外的读取或写入。

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

<a id="multiple-signed-in-users-on-a-single-console" />

## 单个主机上的多个登录用户

当多个用户在同一主机上登录时,某些用户可能在游戏会话中,而其他用户则不在会话中或在当前标题中不活动。
也可以为多个用户接收和接受游戏邀请,从而影响游戏会话成员资格。
在您的标题中考虑此信息,以便它可以正确处理所有会话成员资格场景。

在一个常见场景中,新玩家登录,在游戏中变为活动,并需要添加到现有游戏会话中。
与创建新游戏会话一样,标题应仅在游戏中适当的时候添加用户。

对于多个登录用户,一个或多个用户还可以接收另一个游戏会话的邀请。
标题不需要以任何特定方式处理这些场景。
会话状态和成员事件会通知标题游戏会话和用户成员资格的任何更新。

要为在线会话处理多个登录用户,标题会为所有用户订阅提醒通知,为每个用户使用单独的 `XboxLiveContext Class` 对象。
标题使用 [XblMultiplayerSessionInfo](/reference/live/xsapi-c/multiplayer_c/structs/xblmultiplayersessioninfo)`::ChangeNumber` 属性来确定会话中的特定更改并忽略重复的提醒通知。

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

<a id="process-lifecycle-management" />

## 进程生命周期管理

就像非多人游戏标题一样,处于多人游戏会话中的标题可能会遇到标题暂停和进程生命周期事件的终止。
因此,会话仲裁者应定期保存会话状态。

如果仲裁者被暂停,标题应尝试仲裁者迁移并根据需要保存游戏状态。然后,新的仲裁者可以恢复会话状态。
然后,如果会话在 MPSD 中仍然有效,则完整的多人游戏会话可以被暂停并稍后恢复。

只有一个指定的对等方(通常是游戏主机)应更新全局游戏状态。

### 游戏元数据的存储

标题将游戏元数据存储在 MPSD 会话中。
游戏元数据是显示会话数据和使标题能够查找和加入游戏会话所需的信息。

标题将特定于玩家的元数据存储在会话成员的自定义属性部分中。例如,会话的玩家颜色和首选玩家武器。
会话范围的元数据(如当前地图)存储在 MPSD 会话的全局自定义属性部分中。

### 游戏状态的存储

游戏状态使用标题存储服务存储在 TMS 中。
使用此位置进行存储允许标题在没有权限顾虑的情况下迁移仲裁者。
有关详细信息,请参阅[迁移仲裁者](/services/xbox-services/multiplayer/concepts/live-migrating-an-arbiter)。

<Note>除非被暂停,否则标题不应尝试比每五分钟一次更频繁地将游戏状态保存到 TMS。</Note>

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

<a id="cleanup-of-inactive-sessions" />

## 清理非活动会话

如果将 `sessionEmptyTimeout` 设置为 0,则当最后一位玩家离开会话时,MPSD 会话将自动删除。
要了解如何防止未使用的会话在崩溃或断开连接后包含玩家,请参阅“多人游戏会话目录概述”主题中的 [MPSD 更改通知处理和断开连接检测](/services/xbox-services/multiplayer/mpsd/live-mpsd-overview#mpsd-change-notification-handling-and-disconnect-detection)部分。
崩溃或断开连接后对未使用会话的不当处理可能会导致标题查询玩家的会话时出现问题。

我们建议您通过让标题调用 [XblMultiplayerGetSessionAsync](/reference/live/xsapi-c/multiplayer_c/functions/xblmultiplayergetsessionasync) 查询特定用户的所有会话,然后评估会话,以清理非活动会话。
当标题遇到过时会话时,标题会为会话中的所有本地玩家调用 [XblMultiplayerSessionLeave](/reference/live/xsapi-c/multiplayer_c/functions/xblmultiplayersessionleave)。
此调用最终会将成员计数降至 0 并清理会话。

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

<a id="session-arbiter" />

## 会话仲裁者

某些多人游戏方法应仅由游戏会话中的一个客户端调用。
此客户端是参与会话的主机之一,称为*仲裁者*或主机。
如果至少一名会话成员在游戏中,则会话应有一个仲裁者来监控进行中的加入。

### 设置仲裁者

当客户端创建会话时,它会将一个主机指定为仲裁者。
有关详细信息,请参阅“多人游戏任务”主题中的[为 MPSD 会话设置仲裁者](/services/xbox-services/multiplayer/mpsd/how-to/live-mpsd-how-tos#set-an-arbiter-for-an-mpsd-session)部分。

### 保存会话状态

如[进程生命周期管理](#process-lifecycle-management)部分所述,仲裁者应定期保存会话状态。
在标题进行仲裁者迁移的情况下,新的仲裁者必须能够恢复会话状态。
有关详细信息,请参阅[迁移仲裁者](/services/xbox-services/multiplayer/concepts/live-migrating-an-arbiter)。

### 管理游戏会话成员和进行中的加入

会话仲裁者最重要的角色是管理进入游戏会话进行游戏的用户。
这包括处理游戏邀请、通知等待玩家以及处理退出游戏的玩家。

#### 接收通知

仲裁者必须使用 [XblMultiplayerSessionChangedHandler](/reference/live/xsapi-c/multiplayer_c/functions/xblmultiplayersessionchangedhandler) 侦听想要加入游戏会话的新玩家。

#### 查找玩家以填补空闲的游戏会话位置

仲裁者使用以下操作之一查找玩家以填补空闲的游戏会话位置。

* 如果您的标题使用大厅会话或其他机制来允许延迟加入,请使用该机制查找新的会话成员。
* 创建另一个匹配票证会话。

有关详细信息,请参阅“多人游戏任务”主题中的[在匹配期间填补空闲会话位置](/services/xbox-services/multiplayer/mpsd/how-to/live-mpsd-how-tos#fossdm)部分。

#### 处理受邀会话成员

仲裁者必须监视受邀的会话成员,并在向单个用户发出邀请之间应用最短时间间隔。
有关详细信息,请参阅“多人游戏任务”主题中的[发送游戏邀请](/services/xbox-services/multiplayer/mpsd/how-to/live-mpsd-how-tos#sgi)部分。
