1

我想通过网络服务发现连接多个 Android 设备。我想使用星型拓扑。等等设备应该发现和其他人注册一个应该由发现者发现的服务。为此,我使用了 NSD Chat ( https://github.com/gauravcanon/NsdChat ) NsdHelper 并仅对其进行了一些更改,因此在解决建立连接的服务后会调用回调。如果我使用三个设备,这主要适用。两个广告商和一个发现者。服务得到解决并建立连接。如果我再获得第三个广告商,它会在 80% 的尝试中崩溃。onServiceResolved原因是在函数中传递的serviceInfoResolveListener包含解析电话的 IP 地址,而不是广告电话的 IP 地址。端口正确,服务名称也正确。这是一种奇怪的行为,我不知道如何调试它。我正在使用 bonjour 浏览器查看所有注册的服务,并且所有服务的注册都很好。所有包含正确 IP 地址和端口的服务信息。我还尝试了不建立连接的纯发现过程。同样的失败。有时解析器的 IP 地址在 serviceinfo 中。它也可能发生在第一次发现和第二次发现中,但很可能发生在第三次发现中。我将在下面发布我的 NsdHelper 代码。我现在进行了一些编辑,因为我在解决后尝试再次启动发现过程,因此与 NSD Chat 存在更多差异,但错误仍然存​​在。有人通过 NSDManager 在多个设备上使用 Android 的 NSD 实现吗?它对你有用吗?你在做什么不同?这个话题是相关的,有人遇到了同样的问题(Android、NSD/DNS-SD:NsdManager 不可靠的发现和 IP 解析)。我无法想象这个错误仍然是3年前的事情?

我感谢每一个提示!

    class NsdHelper(private var mContext: Context, private val createClient: (InetAddress, Int)->Unit, val mHandler: Handler) {
internal var mNsdManager: NsdManager = mContext.getSystemService(Context.NSD_SERVICE) as NsdManager
internal lateinit var mResolveListener: NsdManager.ResolveListener
private var mDiscoveryListener: NsdManager.DiscoveryListener? = null
private var mRegistrationListener: NsdManager.RegistrationListener? = null
var mServiceName = "Wizard"
var chosenServiceInfo: NsdServiceInfo? = null
    internal set
val mServices = mutableListOf<NsdServiceInfo>()

fun initializeNsd() {
    stopDiscovery()
    tearDown()
    initializeResolveListener()
}


fun reset(){
    initializeResolveListener()
    discoverServices()
}

fun initializeDiscoveryListener() {
    mDiscoveryListener = object : NsdManager.DiscoveryListener {
        override fun onDiscoveryStarted(regType: String) {
            Log.d(TAG, "Service discovery started")
        }

        override fun onServiceFound(service: NsdServiceInfo) {
            Log.d(TAG, "Service discovery success$service")
            when {
                service.serviceType != SERVICE_TYPE -> Log.d(TAG, "Unknown Service Type: " + service.serviceType)
                service.serviceName == mServiceName -> Log.d(TAG, "Same machine: $mServiceName")
                service.serviceName.contains("Verzauberte") -> {
                    if (mServices.none { it.serviceName == service.serviceName })
                    mNsdManager.resolveService(service, mResolveListener)
                }
            }
        }

        override fun onServiceLost(service: NsdServiceInfo) {
            Log.e(TAG, "service lost$service")
        }

        override fun onDiscoveryStopped(serviceType: String) {
            Log.i(TAG, "Discovery stopped: $serviceType")
        }

        override fun onStartDiscoveryFailed(serviceType: String, errorCode: Int) {
            Log.e(TAG, "Discovery failed: Error code:$errorCode")
        }

        override fun onStopDiscoveryFailed(serviceType: String, errorCode: Int) {
            Log.e(TAG, "Discovery failed: Error code:$errorCode")
        }
    }
}

fun initializeResolveListener() {
    mResolveListener = object : NsdManager.ResolveListener {
        override fun onResolveFailed(serviceInfo: NsdServiceInfo, errorCode: Int) {
            Log.e(TAG, "Resolve failed$errorCode")
        }

        override fun onServiceResolved(serviceInfo: NsdServiceInfo) {
            Log.e(TAG, "Resolve Succeeded. $serviceInfo")
            if (serviceInfo.serviceName == mServiceName) {
                Log.d(TAG, "Same IP.")
                return
            }
            chosenServiceInfo = serviceInfo
            mHandler.post(Runnable {
                createClient(
                    serviceInfo.host,
                    serviceInfo.port
                )
            })
            mServices.add(serviceInfo)
            reset()
        }
    }
}

fun initializeRegistrationListener() {
    mRegistrationListener = object : NsdManager.RegistrationListener {
        override fun onServiceRegistered(NsdServiceInfo: NsdServiceInfo) {
            mServiceName = NsdServiceInfo.serviceName
            Log.d(TAG, "Service registered: $mServiceName")
        }

        override fun onRegistrationFailed(arg0: NsdServiceInfo, arg1: Int) {
            Log.d(TAG, "Service registration failed: $arg1")
        }

        override fun onServiceUnregistered(arg0: NsdServiceInfo) {
            Log.d(TAG, "Service unregistered: " + arg0.serviceName)
        }

        override fun onUnregistrationFailed(serviceInfo: NsdServiceInfo, errorCode: Int) {
            Log.d(TAG, "Service unregistration failed: $errorCode")
        }
    }
}

fun registerService(port: Int) {
    tearDown()  // Cancel any previous registration request
    initializeRegistrationListener()
    val serviceInfo = NsdServiceInfo().apply {
        serviceType = SERVICE_TYPE
        serviceName = "Verzauberte[$port]"
        setPort(port)
    }
    mNsdManager.registerService(
        serviceInfo, NsdManager.PROTOCOL_DNS_SD, mRegistrationListener
    )
}

fun discoverServices() {
    stopDiscovery()  // Cancel any existing discovery request
    initializeDiscoveryListener()
    Log.d(this.toString(), "Start discovering")
    mNsdManager.discoverServices(
        SERVICE_TYPE, NsdManager.PROTOCOL_DNS_SD, mDiscoveryListener
    )
}

fun stopDiscovery() {
    if (mDiscoveryListener != null) {
        try {
            mNsdManager.stopServiceDiscovery(mDiscoveryListener)
        } finally {
        }
        mDiscoveryListener = null
    }
}

fun tearDown() {
    if (mRegistrationListener != null) {
        try {
            mNsdManager.unregisterService(mRegistrationListener)
        } finally {
        }
        mRegistrationListener = null
    }
}



companion object {
    val SERVICE_TYPE = "_votinginteractions._tcp."
    val TAG = "NsdHelper"
}

}

4

0 回答 0