NsdManager 发现两个服务,但是解析ip 和 port 的时候,只能解析一个,什么原因?

时间:2024-10-22 16:03:58

背景:

        当你使用NsdManager发现多个服务并尝试解析IP和端口时,只能解析一个服务。

可能原因:

  1. 竞争条件:如果你尝试同时解析多个服务,可能会出现竞争条件,导致只有一个解析成功。
  2. 服务解析限制:NsdManager可能在某一时刻只允许解析一个服务。
  3. 回调覆盖:如果你使用了同一个ResolveListener实例解析多个服务,可能会导致回调被覆盖,从而只处理最后一个解析的服务。

尝试方法:

  1. 1. 确保每个服务使用单独的ResolveListener实例: 每个服务解析请求应该有自己独立的ResolveListener实例。

  2. 2. 逐一解析服务: 避免同时解析多个服务,而是一个接一个地解析,确保上一个解析完成后再开始下一个。

改动前的代码:

import android.;
import android.net.;
import ;
import ;
import ;

import .concurrent.Executor;
import .Executors;

public class NsdHelper {
    private static final String TAG = "NsdHelper";
    private NsdManager nsdManager;
    private resolveListener;

    public NsdHelper(Context context) {
        nsdManager = (NsdManager) (Context.NSD_SERVICE);
    }

    public void resolveService(@NonNull NsdServiceInfo serviceInfo) {
        Executor executor = ();
        resolveListener = new () {
            @Override
            public void onResolveFailed(NsdServiceInfo serviceInfo, int errorCode) {
                (TAG, "Resolve failed: " + errorCode);
            }

            @Override
            public void onServiceResolved(NsdServiceInfo serviceInfo) {
                (TAG, "Service resolved: " + serviceInfo);
                // Here you can get the resolved service details
                String host = ().getHostAddress();
                int port = ();
                (TAG, "Host: " + host + ", Port: " + port);
            }
        };

        (serviceInfo, executor, resolveListener);
    }
}
 

改动后的代码:

        以下是改进后的Kotlin代码示例,展示了如何处理多个服务的解析:

import
import
import
import
import

class NsdHelper(context: Context) {

    private val nsdManager: NsdManager = (Context.NSD_SERVICE) as NsdManager
    private val executor = ()
    private val serviceQueue = mutableListOf<NsdServiceInfo>()

    fun discoverServices() {
        val discoveryListener = object : {
            override fun onDiscoveryStarted(serviceType: String) {
                (TAG, "Service discovery started")
            }

            override fun onServiceFound(serviceInfo: NsdServiceInfo) {
                (TAG, "Service found: $serviceInfo")
                // 将发现的服务添加到队列中等待解析
                (serviceInfo)
                if ( == 1) {
                    resolveNextService()
                }
            }

            override fun onServiceLost(serviceInfo: NsdServiceInfo) {
                (TAG, "Service lost: $serviceInfo")
                (serviceInfo)
            }

            override fun onDiscoveryStopped(serviceType: String) {
                (TAG, "Service discovery stopped")
            }

            override fun onStartDiscoveryFailed(serviceType: String, errorCode: Int) {
                (TAG, "Service discovery start failed: $errorCode")
                (this)
            }

            override fun onStopDiscoveryFailed(serviceType: String, errorCode: Int) {
                (TAG, "Service discovery stop failed: $errorCode")
                (this)
            }
        }

        ("_http._tcp.", NsdManager.PROTOCOL_DNS_SD, discoveryListener)
    }

    private fun resolveNextService() {
        if (()) return

        val serviceInfo = ()
        val resolveListener = object : {
            override fun onResolveFailed(serviceInfo: NsdServiceInfo, errorCode: Int) {
                (TAG, "Resolve failed: $errorCode")
                (serviceInfo)
                resolveNextService()
            }

            override fun onServiceResolved(serviceInfo: NsdServiceInfo) {
                (TAG, "Service resolved: $serviceInfo")
                val host =
                val port =
                (TAG, "Host: $host, Port: $port")
                (serviceInfo)
                resolveNextService()
            }
        }

        (serviceInfo, executor, resolveListener)
    }

    companion object {
        private const val TAG = "NsdHelper"
    }
}
 

代码解释:

  1. 服务队列:使用一个MutableList来保存发现的服务。
  2. 发现服务:通过discoverServices方法启动服务发现。
  3. 解析服务:在onServiceFound回调中,将发现的服务添加到队列中,并调用resolveNextService方法开始解析。
  4. 逐一解析:resolveNextService方法从队列中取出第一个服务进行解析,并在解析完成或失败后解析下一个服务。

   以上方式确保每次只解析一个服务,从而避免竞争条件和回调覆盖的问题。