14. 实验

该指南包含对服务器的非标准或实验性功能的描述。其中一些基于从未发布的扩展,其中一些只是测试实现以获取新想法或性能改进。

14.1. 动态名册

14.1.1. 问题描述

作为 动态花名册部分 存储和创建的正常花名册联系人透明地交付给最终用户。XMPP客户端并不真正知道哪些联系人来自用户手动创建的自己的**静态**名册,哪些联系人来自 动态 名册部分;联系人和组由服务器逻辑动态生成的。

一些专业客户需要存储有关名册联系人的额外信息。对于普通用户,静态 名册信息可以作为私有数据存储,并且仅供该单个用户使用。然而,在某些情况下,客户端需要存储来自动态名册部分的联系人信息,并且此信息必须可供所有访问 动态 名册部分的用户使用。

此处定义的协议允许交换信息、保存和检索有关联系人的额外数据。

14.1.2. 句法和语义

使用IQ节访问额外的联系人数据,特别是通过 jabber:iq:roster-dynamic 命名空间限定的子元素。子元素可以包含一个或多个子元素,每个子元素描述一个独特的联系人项目。元素的内容未指定,取决于实现。从Tigase的角度来看,它可以包含任何有效的XML数据。整个元素按原样传递给DynamicRoster实现类,无需任何验证。在检索联系人额外数据时,DynamicRoster实现应该提供一个有效的XML元素,其中包含请求的 jid 所需的所有数据。

jid 属性指定唯一标识名册项目的Jabber标识符 (JID)。包含 jid 属性是 必需的

允许对额外联系人数据执行以下操作:

  • set - 存储有关联系人的额外信息

  • get - 检索有关联系人的额外信息

14.1.3. 检索联系人数据

在连接到服务器并成为活动资源后,客户端可以请求额外的联系人数据。可以在请求用户名册之前或之后提出此请求。客户对额外联系数据的请求是 可选的

示例:客户端使用 get 请求从服务器请求联系人额外数据:

<iq type='get' id='rce_1'>
<query xmlns='jabber:iq:roster-dynamic'>
<item jid='[email protected]'/>
</query>
</iq>

示例:客户端从服务器接收到额外的联系人数据,但没有用户的额外信息,或者在动态名册中找不到用户:

<iq type='result' id='rce_1'>
<query xmlns='jabber:iq:roster-dynamic'>
<item jid='[email protected]'/>
</query>
</iq>

示例:客户端从服务器接收到联系人额外数据,并且发现了一些关于联系人的额外信息:

<iq type='result' id='rce_1'>
<query xmlns='jabber:iq:roster-dynamic'>
<item jid='[email protected]'>
<phone>+12 3234 322342</phone>
<note>This is short note about the contact</note>
<fax>+98 2343 3453453</fax>
</item>
</query>
</iq>

14.1.4. 更新/保存有关联系人的额外信息

在任何时候,客户端 可以 更新服务器上的额外联系信息。

示例:客户端使用 set 请求发送联系人额外信息。

<iq type='set' id='a78b4q6ha463'>
<query xmlns='jabber:iq:roster-dynamic'>
<item jid='[email protected]'>
<phone>+22 3344 556677</phone>
<note>he is a smart guy, he knows whether the crown is made from pure gold or not.</note>
</item>
</query>
</iq>

客户端响应服务器:

<iq type='result' id='a78b4q6ha463'/>

客户 可以 在一个请求中更新多个项目的联系人额外信息:

示例:客户端使用带有许多<item/>元素的 set 请求发送联系人额外信息。

<iq type='set' id='a78b4q6ha464'>
<query xmlns='jabber:iq:roster-dynamic'>
<item jid='[email protected]'>
<phone>+22 3344 556677</phone>
<note>he is a smart guy, he knows whether the crown is made from pure gold or not.</note>
</item>
<item jid='[email protected]'>
<phone>+22 3344 556688</phone>
<note>He knows how heavy I am.</note>
</item>
<item jid='[email protected]'>
<phone>+22 3344 556699</phone>
<note>This guy helped me cure my sickness!</note>
</item>
</query>
</iq>

客户端响应服务器:

<iq type='result' id='a78b4q6ha464'/>

14.1.5. 配置

DynamicRoster实现类应该在 config.tdsl 文件中配置:

'sess-man' () {
    'dynamic-rosters' () {
        class (class: package.custom.DynamicRosterImplementation) {}
    }
}

如果您想将配置传递给您的实现,只需在变量上使用 @ConfigField 注释(有关详细信息,请参阅 组件实现 - 第2课 - 配置)。

14.2. 移动优化

14.2.1. 问题描述

在默认配置中,当处理完成时,节会发送到客户端,但在移动环境中,发送或接收数据会由于使用无线电而消耗电池电量。

为节省能源,数据应仅在重要或客户正在等待时才发送给客户。

14.2.2. 解决方案

当移动客户端进入非活动状态时,它通过发送以下节来通知服务器:

<iq type="set" id="xx">
<mobile
  xmlns="http://tigase.org/protocol/mobile#v3"
  enable="true"/>
</iq>

收到节后,服务器开始排队节,其应被发送到移动客户端。什么样的排队节取决于所使用的插件,如果是 Mobile v3 存在节,则排队的节以及作为消息碳的消息节。任何其他节(例如iq或纯消息)都会立即发送到客户端,此时队列中的每个节都会被发送。

当移动客户端进入活动状态时,它通过发送以下节来通知服务器:

<iq type="set" id="xx">
<mobile
  xmlns="http://tigase.org/protocol/mobile#v3"
  enable="false"/>
</iq>

收到节后,服务器将所有排队的节发送给客户端。

如果队列中的节数将达到队列大小限制,则队列中的所有节将被发送。默认情况下,此限制设置为50。

14.2.3. 排队算法

Tigase共有三个移动优化插件:

  • Mobile v1 - 所有存在节都保留在队列中

  • Mobile v2 - 只有来自每个来源的最后一次出现才保留在队列中

  • Mobile v3 - 只有来自每个源的最后一次存在保留在队列中,消息碳也排队

如果您希望激活您的Mobile v1插件,您需要发送上面显示的xmlns属性值替换为 http://tigase.org/protocol/mobile#v1

如果您希望激活您的Mobile v2插件,您需要发送上面显示的xmlns属性值替换为 http://tigase.org/protocol/mobile#v2

14.2.4. 配置

移动插件默认不激活,因此需要在 config.tdsl 中添加额外条目:

'sess-man' () {
    mobile_v1 () {}
}

您可以根据您希望使用的算法将 mobile_v1 替换为 mobile_v2mobile_v3

备注

一次只能使用一个插件!

14.3. Bosh会话缓存

14.3.1. 问题描述

Web客户端无法在客户端本地存储任何数据。因此,在重新加载网页后,Web客户端会丢失在重新加载页面之前运行的所有上下文。

可以从服务器检索上下文的某些元素,例如名册和所有联系人的存在信息。但是,其他一些数据无法轻松恢复,例如打开的聊天窗口和聊天窗口的内容。即使可以进行名册恢复,该操作在服务器端的时间和资源方面代价也是非常昂贵的。

一种可能的解决方案是允许Web客户端在Bosh会话处于活动状态时将一些数据存储在服务器端的Bosh组件缓存中。页面重新加载后,如果客户端能够以某种方式检索SID(存储在cookie中或由运行Web客户端的Web应用程序提供),则可以将存储在 Bosh缓存中的所有数据重新加载到客户端。

Bosh会话上下文数据是:名册、联系人状态信息、打开的聊天窗口、聊天窗口内容和其他一些次要数据。理想情况下,Web客户端应该能够将任何数据存储在它想要的Bosh组件缓存中。

14.3.2. Bosh会话缓存说明

Bosh Session Cache分为两部分 - 自动缓存和动态缓存。

将缓存分成两部分的原因是,一些数据可以由Bosh组件自动收集,并且要求客户端将数据存储在Bosh缓存中,这会非常低效。此类数据的最佳示例是名册和联系人存在信息。

  • 自动缓存 - 是由Bosh组件自动创建的缓存部分,无需与客户端进行任何交互。但是,客户端可以随时访问缓存。我会说这是一个只读缓存,但我不想阻止客户端在需要时操作缓存。客户端通常只从这部分缓存中检索数据,因为所有更改都应该由Bosh组件自动更新。自动缓存的总体思路是存储在那里的数据可以以标准的XMPP形式访问。所以不需要额外的代码来处理它们。

  • 动态缓存 - 是客户端可以随时修改或可以修改的缓存部分。客户端可以在这部分缓存中存储、检索、删除和修改数据。

14.3.3. 缓存协议

所有Bosh会话缓存操作都使用附加的<body/>元素属性执行:cachecache-id。如果操作属性需要,属性缓存是存储在 Bosh cache 上执行的操作,cache-id 属性指的是 cache 元素。 cache-id 是可选的。有一个默认的缓存ID(空的)与未提供 cache-id 的元素相关联。

如果 <body/> 元素包含缓存属性,则意味着 <body/> 中包含的所有数据都引用缓存操作。这是不允许的,例如在正文中发送消息并将缓存操作设置为 get。具有缓存操作 getget_allonoffremove<body/> 元素必须为空。带有动作 setadd<body/> 元素必须包含要存储在缓存中的数据。

缓存操作

  • onoff - 客户端可以在会话期间随时打开或关闭缓存。但是,建议客户端在第一个主体数据包中切换缓存 on,否则可能会丢失自动缓存中的某些信息。自动缓存是从通过Bosh组件的数据流创建的。因此,如果在名册检索完成后打开缓存,则名册信息将在缓存中丢失。如果缓存设置为 off (默认值),所有对缓存的请求都将被忽略。这是为了确保与原始Bosh规范的向后兼容性,并确保在默认环境中,Bosh组件不会为缓存处理和存储消耗任何额外资源,因为客户端无论如何都不会使用缓存。

  • get - 从Bosh缓存中检索由cache-id指向的缓存元素。请注意,没有 result 缓存操作。作为响应从服务器发送到客户端的 <body/> 可能包含给定缓存ID的缓存结果,它还可能包含Bosh组件为客户端接收的其他数据。也可能发生大缓存数据被分成几个部分,每个部分可以在一个单独的 <body/> 元素中发送。名册数据通常会发生这种情况。

  • get_all - 检索保存在Bosh缓存中的所有元素。该操作可以在页面重新加载后执行。客户端不必逐个请求每个缓存项。它可以一次检索所有缓存项。然而,这并不意味着整个缓存在单个 <body/> 元素中发送到客户端。缓存内容将被划分为合理大小的较小部分,并在单独的 <body/> 元素中发送到客户端。 ** <body/> ** 元素也可能包含缓存元素以及发送给用户的新请求,例如新消息或存在信息。

  • set - 将数据发送到Bosh Session缓存以供以后检索。客户端可以在缓存中存储它想要的任何数据。 Bosh组件将 <body/> 元素内的所有数据存储在所选ID下的缓存中。唯一的限制是缓存的数据必须是有效的XML内容。数据以与从服务器接收到的完全相同的形式返回给客户端。 set 操作将替换此ID下任何以前存储的数据。

  • add - 将新元素添加到给定ID下的缓存中。此操作对于为打开的聊天窗口存储数据可能很有用。客户端可以为聊天窗口添加新元素,比如新消息、图标等等……​

  • remove - 删除给定缓存ID的缓存元素。

缓存ID

缓存ID可以是任意字符串。可能会为特殊情况保留一些ID,例如用于名册内容。为避免将来出现任何ID冲突,保留的ID值以:bosh - 字符串开头。

有一个默认缓存ID - 一个空字符串。因此可以省略cache-id属性,然后请求引用存储在默认(空)ID下的数据。

保留的缓存ID名称

以下是保留的缓存ID列表:

  • bosh-roster - 用户名册以与从核心服务器接收到的完全相同的形式缓存在Bosh组件中。 Bosh缓存可能会也可能不会对名册进行优化,例如如果名册 删除 已收到,则从缓存的名册中删除元素,或者可能只存储所有名册请求,然后将它们全部发送到客户端。 Bosh Cache必须执行一项强制优化。它必须记住每个花名册项目的最后一个(也是唯一的最后一个)存在状态。在从缓存中检索名册后,Bosh 组件必须先发送名册项目,然后再发送该项目的存在。如果存在缺失,则意味着离线存在。如果名册很小,可以在单个数据包中发送给客户端,但对于大型名册,建议将联系人列表拆分为最多100个元素的批次。 Bosh组件可以先发送所有名册联系人,然后发送所有存在信息,或者它可以发送名册的一部分、已发送项目的存在信息、名册的下一部分、下一个项目的存在信息等等。

  • bosh-resource-bind - 用户资源绑定也被缓存,以允许客户端快速检索有关已建立Bosh会话的完整JID的信息。