You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何取消Smack发送的服务器能力探测请求(disco#info)

如何阻止Smack向muclight、pubsub等服务发送disco#info请求

我完全理解你的场景:你固定和同一服务器通信,已经明确知晓它支持的服务能力,不需要Smack自动发送这些disco#info请求——尤其是那些在认证回调触发前就发出的请求。

先把你监测到的请求示例整理出来:

<iq to='muclight.server.com' from='id@server.com/R' id='yN82u-18' type='get'><query xmlns='http://jabber.org/protocol/disco#info'></query></iq>
<iq to='pubsub.serve.com' from='id@server/R' id='yN82u-20' type='get'><query xmlns='http://jabber.org/protocol/disco#info'></query></iq>
<iq to='upload.server.com' from='id@server/R' id='yN82u-24' type='get'><query xmlns='http://jabber.org/protocol/disco#info'></query></iq>
<iq to='vjud.server.com' from='id@server/R' id='yN82u-22' type='get'><query xmlns='http://jabber.org/protocol/disco#info'></query></iq>

这些请求是Smack默认的自动服务发现机制触发的,尤其是在初始化MucLight、PubSub等服务管理器时,Smack会主动查询服务的能力。下面是几个可行的解决方案:

1. 禁用全局自动服务发现

Smack的ServiceDiscoveryManager是处理所有disco相关逻辑的核心类,你可以直接关闭自动发现服务的功能:

// 获取当前连接的ServiceDiscoveryManager实例
ServiceDiscoveryManager sdm = ServiceDiscoveryManager.getInstanceFor(yourXmppConnection);
// 禁用自动发现远程服务
sdm.setAutoDiscoverServices(false);

这个方法会阻止Smack主动向服务器上的各个服务发送disco#info请求,但要注意:如果你的代码中有其他依赖自动发现的逻辑,可能需要手动适配。

2. 手动注入已知服务的能力信息

如果你不想完全禁用自动发现,而是针对特定服务提前注入已知的能力,Smack就不会再发送请求去查询这些服务:

ServiceDiscoveryManager sdm = ServiceDiscoveryManager.getInstanceFor(yourXmppConnection);

// 针对muclight服务注入信息
Jid mucLightJid = JidCreate.from("muclight.server.com");
sdm.addFeature(mucLightJid, "urn:xmpp:muclight:0"); // 添加服务支持的特性
sdm.addIdentity(mucLightJid, "conference", "muclight"); // 添加服务身份标识

// 针对pubsub服务注入信息
Jid pubSubJid = JidCreate.from("pubsub.server.com");
sdm.addFeature(pubSubJid, "http://jabber.org/protocol/pubsub");
sdm.addIdentity(pubSubJid, "pubsub", "publish-subscribe");

// 同理,为upload、vjud等服务添加对应的特性和身份

这样当Smack需要检查这些服务的能力时,会直接使用你预先注入的信息,无需发送请求。

3. 延迟初始化服务管理器到认证完成后

你提到请求是在连接管理器的auth回调触发前发出的,这通常是因为你在连接建立初期就初始化了MucLightManager、PubSubManager等实例。

解决方法很简单:将这些服务管理器的初始化代码移到认证成功的回调中,确保只有在认证完成后才创建这些实例,这样Smack就不会提前发送disco请求了。

示例代码:

yourXmppConnection.addConnectionListener(new ConnectionListener() {
    @Override
    public void authenticated(XMPPConnection connection, boolean resumed) {
        // 认证成功后才初始化服务管理器
        MucLightManager mucLightManager = MucLightManager.getInstanceFor(connection, JidCreate.from("muclight.server.com"));
        PubSubManager pubSubManager = PubSubManager.getInstanceFor(connection, JidCreate.from("pubsub.server.com"));
        // 后续业务逻辑
    }

    // 其他回调方法...
});

4. 针对特定服务管理器禁用发现

部分Smack服务管理器提供了直接跳过disco发现的配置(取决于Smack版本),比如PubSubManager可以通过构造方法直接指定服务JID,并且不需要自动发现:

// 直接指定pubsub服务的JID,跳过自动发现
PubSubManager pubSubManager = new PubSubManager(yourXmppConnection, JidCreate.from("pubsub.server.com"));
// 如果版本支持,可调用相关方法禁用发现
// pubSubManager.setDiscoveryEnabled(false);

你可以查看对应服务管理器的API文档,确认是否有类似的配置选项。


内容的提问来源于stack exchange,提问作者user2934930

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.09 10:22:27