JmDNS 多设备注册及查找

由于mdns官方sample中是JmDNS.create()创建的,但是我就遇到了有的客户端设备可以被发现有的不可以被发现,所以就尝试用

JmDNS.create(InetAddress.getByName(ip),"RegisterDevices");

才让所以设备都能正常。供参考。希望如果遇到同样的问题时,你可以试试这个。

注册客户端:

public class RegisterMdns {
    private ExecutorService mExecutorService = Executors.newSingleThreadExecutor();
    private final static String REMOTE_TYPE = "_sample._tcp.local.";//注册的type是这个的话,你的发现设备的代码中的type也是这个才能找到这个设备。
    private int PORT = 1025;//默认端口号,可能会与实际端口有冲突,所以代码中加了动态获取端口号的逻辑

    private static JmDNS jmdns;

    public RegisterMdns() {
    }
    private ServiceInfo mServiceInfo;
    public void start(final String ip) {
		/**
		动态获取端口
		*/
        int localPort = 0;
        ServerSocket serverSocket = null;
        try {
            serverSocket = new ServerSocket(0);
            localPort = serverSocket.getLocalPort();
        } catch (IOException e) {
            e.printStackTrace();
        }
        if (localPort!=0)
            PORT = localPort;
        mExecutorService.execute(new Runnable() {
            @Override
            public void run() {
				/**
				  这个ip是手机或盒子的ip地址
				*/
                try {
                    jmdns = JmDNS.create(InetAddress.getByName(ip),"RegisterDevices");
                    final HashMap<String, String> values = new HashMap<String, String>();
                    values.put("test", "vlaue");
                  
                    mServiceInfo = ServiceInfo.create(REMOTE_TYPE, name, PORT, 0, 0, values);
                    jmdns.registerService(mServiceInfo);
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
        });
    }


    public void close() {
        mExecutorService.execute(new Runnable() {
            @Override
            public void run() {
                if (jmdns != null) {
                    try {
                        if (mServiceInfo != null) {
                            jmdns.unregisterService(mServiceInfo);
                        }
                        jmdns.close();
                    } catch (IOException e) {
                        e.printStackTrace();
                    }
                }
            }
        });
    }
}

查找设备端:查找并ui显示

public class DiscoverServices {
    private final static ExecutorService executorService = Executors.newCachedThreadPool();
    public final static String REMOTE_TYPE = "_sample._tcp.local.";
    static class SampleListener implements ServiceListener {
        private Handler mHandler;
        private TextView mTextView;
        private StringBuilder stringBuilder = new StringBuilder();
        public SampleListener(Handler handler,TextView resultView) {
            mHandler = handler;
            mTextView = resultView;
        }
        @Override
        public void serviceAdded(ServiceEvent event) {
          
        }

        @Override
        public void serviceRemoved(ServiceEvent event) {
           
            System.out.println("Service removed : " + event.getName() + "." + event.getType());
        }
        private int count=0;
        @Override
        public void serviceResolved(final ServiceEvent event) {
            mHandler.post(new Runnable() {
                @Override
                public void run() {
                    ServiceInfo serviceInfo;
                    if (event != null) {
                        count++;
                        serviceInfo = event.getInfo();
                        stringBuilder.append(""+count+": name:"+ serviceInfo.getName() + " type: " + serviceInfo.getType() +" version="+serviceInfo.getPropertyString("version")+" uuid="+serviceInfo.getPropertyString("uuid")+" roomNumber="+serviceInfo.getPropertyString("roomNumber")+ " WanIpAddress="+serviceInfo.getPropertyString("WanIpAddress")+" BoxIpAddress="+serviceInfo.getPropertyString("BoxIpAddress")+"\n");
                        mTextView.setText(stringBuilder.toString());
                    }

                }
            });
          
            System.out.println("Service resolved: " + event.getInfo());
        }
    }

    private static JmDNS jmDNS;
    public static void start(final Context context, final Handler handler, final TextView resultView) {
        executorService.execute(new Runnable() {
            @Override
            public void run() {
              
                try {
                    WifiManager wifiManager = (WifiManager) context.getSystemService(Context.WIFI_SERVICE);
                    InetAddress deviceIpAddress = getDeviceIpAddress(wifiManager);

                    WifiManager.MulticastLock multicastLock = wifiManager.createMulticastLock("ListServices");
                    multicastLock.setReferenceCounted(true);
                    multicastLock.acquire();

                    jmDNS = JmDNS.create(deviceIpAddress,"FindDevice");
                    jmDNS.addServiceListener(REMOTE_TYPE, new SampleListener(handler,resultView));
                   /* while (!close) {
                        ServiceInfo[] list = jmDNS.list(REMOTE_TYPE);
                        for (ServiceInfo item : list) {
                            String name = item.getName();
                            String type = item.getType();
                         
                        }
                        try {
                            Thread.sleep(5000);
                        } catch (InterruptedException e) {
                            e.printStackTrace();
                        }
                    }*/

                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
        });

    }
    private static  boolean close=false;
    public static void close(){
        executorService.execute(new Runnable() {
            @Override
            public void run() {
               
                if (jmDNS != null) {
                    try {
                        close=true;
                        jmDNS.close();
                    } catch (IOException e) {
                        e.printStackTrace();
                    }
                }
            }
        });
    }
    private static InetAddress getDeviceIpAddress(WifiManager wifi) {
        InetAddress result = null;
        try {
            // default to Android localhost
            result = InetAddress.getByName("10.0.0.2");

            // figure out our wifi address, otherwise bail
            WifiInfo wifiinfo = wifi.getConnectionInfo();
            int intaddr = wifiinfo.getIpAddress();
            byte[] byteaddr = new byte[] { (byte) (intaddr & 0xff), (byte) (intaddr >> 8 & 0xff), (byte) (intaddr >> 16 & 0xff), (byte) (intaddr >> 24 & 0xff) };
            result = InetAddress.getByAddress(byteaddr);
        } catch (UnknownHostException ex) {
            Log.w(LogUtils.TAG, String.format("getDeviceIpAddress Error: %s", ex.getMessage()));
        }

        return result;
    }
}


  • 1
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
利用jmdns发现局域网设备,在局域网内,你要通过一台主机和其他主机进行通信,你需要知道对方的ip地址,但是有些时候,你并不知道对方的ip地址,因为一般使用DHCP动态分配ip地址的局域网内,各个主机的IP地址是由DHCP服务器来帮你分配IP地址的。所以在很多情况下,你要知道对方的IP地址是比较麻烦的。 鉴于发现这篇文章最近的浏览量比较多,晚上也有不少转载,特别声明一下,文章水平可能不大够,只是我当时的一些理解,所以希望大家以批判的角度来看,然后又什么问题欢迎讨论。真心不希望误导大家^_^ mDNS就是来解决这个问题的。通过一个约定俗成的端口号,5353。(这个端口号应该是由IETF组织约定的。)每个进入局域网的主机,如果开启了mDNS服务的话,都会向局域网内的所有主机组播一个消息,我是谁,和我的IP地址是多少。然后其他也有该服务的主机就会响应,也会告诉你,它是谁,它的IP地址是多少。当然,具体实现要比这个复杂点。 比如,A主机进入局域网,开启了mDNS服务,并向mDNS服务注册一下信息:我提供FTP服务,我的IP是192.168.1.101,端口是21。当B主机进入局域网,并向B主机的mDNS服务请求,我要找局域网内FTP服务器,B主机的mDNS就会去局域网内向其他的mDNS询问,并且最终告诉你,有一个IP地址为192.168.1.101,端口号是21的主机,也就是A主机提供FTP服务,所以B主机就知道了A主机的IP地址和端口号了。 大概的原理就是这样子,mDNS提供的服务要远远多于这个,当然服务多但并不复杂。 在Apple 的设备上(电脑,笔记本,iphone,ipad等设备)都提供了这个服务。很多Linux设备也提供这个服务。Windows的设备可能没有提供,但是如果安装了iTunes之类的软件的话,也提供了这个服务。 这样就可以利用这个服务开发一些局域网内的自动发现,然后提供一些局域网内交互的应用了。
要使用mDNS协议来发现网络服务,可以使用Android的NSD API中的discoveryListeners参数。具体来说,您需要创建一个NsdManager.DiscoveryListener对象,并在其onStartDiscovery()方法中指定协议类型为PROTOCOL_MDNS,然后将该对象作为discoveryListeners参数传递给nsdManager.discoverServices()方法。 以下是使用mDNS协议发现网络服务的示例代码: ``` NsdManager nsdManager = (NsdManager) getSystemService(Context.NSD_SERVICE); NsdManager.DiscoveryListener discoveryListener = new NsdManager.DiscoveryListener() { @Override public void onStartDiscovery(String serviceType) { nsdManager.discoverServices(serviceType, NsdManager.PROTOCOL_MDNS, discoveryListener); } //... }; nsdManager.discoverServices("_http._tcp", NsdManager.PROTOCOL_MDNS, discoveryListener); ``` 在上面的代码中,我们创建了一个名为_discoveryListener的NsdManager.DiscoveryListener对象,并在其onStartDiscovery()方法中指定协议类型为PROTOCOL_MDNS。然后,我们调用nsdManager.discoverServices()方法来开始发现_http._tcp服务,同时将_discoveryListener对象作为discoveryListeners参数传递给该方法。 请注意,使用mDNS协议发现网络服务需要在AndroidManifest.xml文件中添加以下权限: ``` <uses-permission android:name="android.permission.INTERNET"/> <uses-permission android:name="android.permission.ACCESS_NETWORK_STATE"/> ``` 同时,您还需要在gradle.build文件中添加以下依赖项: ``` implementation 'androidx.jmdns:jmdns:3.5.5' ``` 这是因为Android的NSD API并不直接支持mDNS协议,而是使用第三方库jmdns来实现该协议。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值