【问题标题】:Android NSD: Why service type don't matchAndroid NSD:为什么服务类型不匹配
【发布时间】:2018-11-28 00:12:25
【问题描述】:

我创建了一个应用来测试 android 上的网络服务发现 (NSD)。

失败的场景

运行该应用的两台设备。我在第一台设备上点击了 register,在看到确认注册的 toast 之后,我在另一台设备上点击了 discover

第二台设备发现了该服务,但输入的是未知的。从调试我看到未知的服务类型是

_mynsd._tcp.

但是当服务被注册时,类型被设置为

_mynsd._tcp // (without the dot at the end)

我认为我没有做过改变服务类型的事情。 这是活动:

public class MainActivity extends AppCompatActivity {
    private static final String SERVICE_TYPE = "_mynsd._tcp";

    private ServerSocket serverSocket;
    private int localPort;

    private NsdManager.RegistrationListener registrationListener;
    private NsdManager.DiscoveryListener discoveryListener;
    private NsdManager nsdManager;
    private String serviceName;
    private NsdServiceInfo service;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        initializeRegistrationListener();
        initializeServerSocket();
        nsdManager = (NsdManager) getSystemService(NSD_SERVICE);
    }

    public void onRegisterClicked(View view) {
        registerService(localPort);
    }

    public void onDiscoverClicked(View view) {
        if (discoveryListener == null)
            initializeDiscoveryListener();
        nsdManager.discoverServices(SERVICE_TYPE, NsdManager.PROTOCOL_DNS_SD, discoveryListener);
    }

    public void onConnectClicked(View view) {

    }

    @Override
    protected void onPause() {
        super.onPause();
        if (nsdManager != null)
            nsdManager.unregisterService(registrationListener);
    }

    public void registerService(int port) {
        NsdServiceInfo serviceInfo = new NsdServiceInfo();
        serviceInfo.setServiceName("MyNsd");
        serviceInfo.setServiceType(SERVICE_TYPE);
        serviceInfo.setPort(port);

        nsdManager.registerService(serviceInfo, NsdManager.PROTOCOL_DNS_SD, registrationListener);
    }

    public void initializeServerSocket() {
        try {
            serverSocket = new ServerSocket(0);
            localPort = serverSocket.getLocalPort();
        } catch (IOException e) {
            Toast.makeText(this, "Error with server socket", Toast.LENGTH_SHORT).show();
        }
    }

    public void initializeDiscoveryListener() {
        discoveryListener = new NsdManager.DiscoveryListener() {
            @Override
            public void onStartDiscoveryFailed(String s, int i) {
                Toast.makeText(MainActivity.this, "Start discovery failed", Toast.LENGTH_SHORT).show();
            }

            @Override
            public void onStopDiscoveryFailed(String s, int i) {
                Toast.makeText(MainActivity.this, "Stop discovery failed ", Toast.LENGTH_SHORT).show();
            }

            @Override
            public void onDiscoveryStarted(String s) {
                Toast.makeText(MainActivity.this, "Started discovery", Toast.LENGTH_SHORT).show();
            }

            @Override
            public void onDiscoveryStopped(String s) {
                Toast.makeText(MainActivity.this, "Stopped discovery", Toast.LENGTH_SHORT).show();
            }

            @Override
            public void onServiceFound(NsdServiceInfo nsdServiceInfo) {
                Toast.makeText(MainActivity.this, nsdServiceInfo.getServiceName() + " service found", Toast.LENGTH_SHORT).show();

                if (!nsdServiceInfo.getServiceType().equals(SERVICE_TYPE)) {
                    Toast.makeText(MainActivity.this, "Unknown service type "+nsdServiceInfo.getServiceType(), Toast.LENGTH_SHORT).show();
                } else if (nsdServiceInfo.getServiceName().equals(serviceName)) {
                    // The one who registered the service is the one which actually holds the
                    // service name and its not null, so if we are here its the same machine
                    // who registered the service in the first place.
                    Toast.makeText(MainActivity.this, "Same machine: " + serviceName, Toast.LENGTH_SHORT).show();
                } else if (nsdServiceInfo.getServiceName().contains("MyNsd")) {
                    nsdManager.resolveService(nsdServiceInfo, new NsdManager.ResolveListener() {
                        @Override
                        public void onResolveFailed(NsdServiceInfo nsdServiceInfo, int i) {
                            Toast.makeText(MainActivity.this, "Could not resolve " + nsdServiceInfo.getServiceName(), Toast.LENGTH_SHORT).show();
                        }

                        @Override
                        public void onServiceResolved(NsdServiceInfo nsdServiceInfo) {
                            Toast.makeText(MainActivity.this, "Resolved  " + nsdServiceInfo.getServiceName(), Toast.LENGTH_SHORT).show();
                            if (nsdServiceInfo.getServiceName().equals(serviceName)){
                                Toast.makeText(MainActivity.this, "Same IP", Toast.LENGTH_SHORT).show();
                                return;
                            }

                            service = nsdServiceInfo;
                            int port = service.getPort();
                            InetAddress host = service.getHost();
                        }
                    });
                }
            }

            @Override
            public void onServiceLost(NsdServiceInfo nsdServiceInfo) {
                Toast.makeText(MainActivity.this, nsdServiceInfo.getServiceName() + " service lost", Toast.LENGTH_SHORT).show();
            }
        };
    }

    public void initializeRegistrationListener() {
        registrationListener = new NsdManager.RegistrationListener() {
            @Override
            public void onRegistrationFailed(NsdServiceInfo nsdServiceInfo, int i) {
                Toast.makeText(MainActivity.this, "Registration failed!", Toast.LENGTH_SHORT).show();
            }

            @Override
            public void onUnregistrationFailed(NsdServiceInfo nsdServiceInfo, int i) {
                Toast.makeText(MainActivity.this, "Unregistration failed", Toast.LENGTH_SHORT).show();
            }

            @Override
            public void onServiceRegistered(NsdServiceInfo nsdServiceInfo) {
                Toast.makeText(MainActivity.this, "Service registered", Toast.LENGTH_SHORT).show();
                serviceName = nsdServiceInfo.getServiceName();
            }

            @Override
            public void onServiceUnregistered(NsdServiceInfo nsdServiceInfo) {
                Toast.makeText(MainActivity.this, "Service unregistered", Toast.LENGTH_SHORT).show();
            }
        };
    }
}

这是布局:

<?xml version="1.0" encoding="utf-8"?>
<android.support.constraint.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    tools:context=".MainActivity">

    <Button
        android:id="@+id/register"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_marginStart="8dp"
        android:layout_marginLeft="8dp"
        android:layout_marginTop="8dp"
        android:onClick="onRegisterClicked"
        android:text="Register"
        app:layout_constraintStart_toStartOf="parent"
        app:layout_constraintTop_toTopOf="parent" />

    <Button
        android:id="@+id/discover"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_marginStart="8dp"
        android:layout_marginLeft="8dp"
        android:layout_marginTop="8dp"
        android:onClick="onDiscoverClicked"
        android:text="Discover"
        app:layout_constraintStart_toEndOf="@+id/register"
        app:layout_constraintTop_toTopOf="parent" />

    <Button
        android:id="@+id/connect"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_marginStart="8dp"
        android:layout_marginLeft="8dp"
        android:layout_marginTop="8dp"
        android:onClick="onConnectClicked"
        android:text="connect"
        app:layout_constraintStart_toEndOf="@+id/discover"
        app:layout_constraintTop_toTopOf="parent" />
</android.support.constraint.ConstraintLayout>

【问题讨论】:

    标签: java android service-discovery nsd


    【解决方案1】:

    您必须以SRV 记录的形式在DNS 中注册它,然后才会知道它。可能,如果您将一台设备设置为另一台设备的名称服务器,那么在localhost 上的注册可能会成功。解释过一次here;那是云 DNS,但任何本地名称服务器都可以满足 localdomain

    回答实际问题:它是绝对域名(带有尾随 .)与相对域名。

    【讨论】:

    • 你好,马丁。我觉得你是对的,但我还是不明白我的错误是什么。我几乎从文档中复制了代码。他们也有一个关于它的视频。例如,他们将类型设置为serviceInfo.setServiceType("_nsdchat._tcp");。好吧,我也这样做了,只是更改了我的应用程序的名称_mynsd._tcp
    • 我相信系统已经以某种方式实现了基于 DNS 的服务发现 (DNS-SD) 机制。
    • @Skemelio 在没有查看 NSD 文档的情况下,target 主机名和 port 将是告诉主机运行发现它可以连接到哪里的最少需要。尾随 . 应该只用于 DNS 中的条目,否则不需要。
    • 是的@Martin Zeitler,有一个NsdServiceInfo 对象将所有这些信息包装在其中,当然,在您提供它们之后。
    • @Skemelio 在这里解释:dns-sd.org/trailingdotsindomainnames.html
    猜你喜欢
    • 1970-01-01
    • 2021-06-27
    • 2010-12-13
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多