一. 简介

网络服务发现:一般是指通过此功能,在局域网内来发现同样支持此功能的设备,并跟其他设备建立连接。

Android 提供了一个网络服务发现(NSD),可让应用访问其他设备在本地网路上提供的服务。

NSD 实现了基于 DNS 的服务发现 (DNS-SD) 机制,该机制允许您的应用通过指定服务类型和提供所需类型服务的设备实例的名称来请求服务。Android 和其他移动平台均支持 DNS-SD。其实NSD是基于iOS的Bonjour服务发现协议实现的,所以使用NSD可以与iOS进行跨平台交互。

NSD(NsdManager)是Android SDK中自带的类库,可以集成直接使用。使用 NSD服务需要android4.1及以上 minSdkVersion >16

二. NSD的两个功能

(1)NSD注册功能
​ 进行NSD注册:自定义服务名、端口号,IP地址注册到NSD服务中。
(2)NSD扫描功能
​ 扫描到当前局域网内所有已通过NSD注册了的应用设备的网络信息(服务名、端口号、IP地址)

三. 需要先了解的

  • NsdManager:系统自带类库,可以通过getSystemService(NSD_SERVICE) 获取这个对象;
  • NsdServiceInfo:此对象提供你的服务时的网络信息(服务名、端口号、IP地址)。

四. NSD 服务端实现

步骤如下:

  1. NsdManager初始化
NsdManager nsdManager = (NsdManager) getSystemService(NSD_SERVICE);
  1. 创建一个server来获取端口
   try {ServerSocket mServerSocket = new ServerSocket(0);//设为0,会自动获取没有占用的端口int mPort = mServerSocket.getLocalPort();} catch (IOException e) {e.printStackTrace();}
  1. 创建NsdServiceInfo
NsdServiceInfo mNsdServiceInfo = new NsdServiceInfo();
mNsdServiceInfo.setServiceName(SERVICE_NAME);// 设置服务名
mNsdServiceInfo.setServiceType(SERVICE_TYPE);// 设置服务类型
mNsdServiceInfo.setPort(mPort);// 设置端口号
  1. 创建注册监听
private void createRegistration() {mRegistrationListener = new NsdManager.RegistrationListener() {@Overridepublic void onRegistrationFailed(NsdServiceInfo nsdServiceInfo, int i) {// 注册失败回调Toast.makeText(MainActivity.this, "onRegistrationFailed", Toast.LENGTH_SHORT).show();}@Overridepublic void onUnregistrationFailed(NsdServiceInfo nsdServiceInfo, int i) {// 取消注册失败Toast.makeText(MainActivity.this, "onUnregistrationFailed", Toast.LENGTH_SHORT).show();}@Overridepublic void onServiceRegistered(NsdServiceInfo nsdServiceInfo) {// 注册服务成功Toast.makeText(MainActivity.this, "onServiceRegistered", Toast.LENGTH_SHORT).show();}@Overridepublic void onServiceUnregistered(NsdServiceInfo nsdServiceInfo) {// 取消注册成功Toast.makeText(MainActivity.this, "onServiceUnregistered", Toast.LENGTH_SHORT).show();}};}
  1. 注册
mNsdManager = (NsdManager) getSystemService(NSD_SERVICE);
mNsdManager.registerService(mNsdServiceInfo, NsdManager.PROTOCOL_DNS_SD, mRegistrationListener);

第2步创建NsdServiceInfo,调用各种set方法,是为了给客户端信息,客户端通过get方法可以拿到相应的信息。

第4步注册中的NsdManager.PROTOCOL_DNS_SD是基于Dns的服务发现协议。

五. 客户端实现

步骤如下:

  1. NsdManager初始化nsdManager = (NsdManager) getSystemService(NSD_SERVICE);
  2. 创建两个监听器。分别是ResolveListenerDiscoveryListener分别来监听NsdServiceInfo的信息和服务的链接成功和失败。
// 这个主要回调,解析搜索到的设备的NsdServiceInfo信息
private void createResolverListener() {mResolverListener = new NsdManager.ResolveListener() {@Overridepublic void onResolveFailed(NsdServiceInfo nsdServiceInfo, int i) {Toast.makeText(MainActivity.this, "onResolveFailed", Toast.LENGTH_SHORT).show();}@Overridepublic void onServiceResolved(NsdServiceInfo nsdServiceInfo) {mNsdServiceInfo = nsdServiceInfo;}};}
// 这个主要是监听搜索结果
private void createDiscoverListener() {mDiscoveryListener = new NsdManager.DiscoveryListener() {@Overridepublic void onStartDiscoveryFailed(String s, int i) {// 开始搜索失败Toast.makeText(MainActivity.this, "onStartDiscoveryFailed", Toast.LENGTH_SHORT).show();}@Overridepublic void onStopDiscoveryFailed(String s, int i) {// 结束搜索失败Toast.makeText(MainActivity.this, "onStopDiscoveryFailed", Toast.LENGTH_SHORT).show();}@Overridepublic void onDiscoveryStarted(String s) {// 开始搜索成功Toast.makeText(MainActivity.this, "onDiscoveryStarted", Toast.LENGTH_SHORT).show();}@Overridepublic void onDiscoveryStopped(String s) {// 停止搜索Toast.makeText(MainActivity.this, "onDiscoveryStopped", Toast.LENGTH_SHORT).show();}@Overridepublic void onServiceFound(NsdServiceInfo nsdServiceInfo) {// 搜索到服务信息mmNsdServiceInfo = nsdServiceInfo;//这里的nsdServiceInfo只能获取到名字,ip和端口都不能获取到,要想获取到需要调用NsdManager.resolveService方法Toast.makeText(MainActivity.this, "onServiceFound", Toast.LENGTH_SHORT).show();}@Overridepublic void onServiceLost(NsdServiceInfo nsdServiceInfo) {//    服务丢失,也就是对面的服务断开了。Toast.makeText(MainActivity.this, "onServiceLost", Toast.LENGTH_SHORT).show();}};}

DiscoveryListener这个监听中的NsdServiceInfo只能获取到名字,ip和端口都不能获取到,要想获取到需要调用NsdManager.resolveService方法。

  1. 发现周边的NSD相关网络
nsdManager.discoverServices(SERVICE_TYPE, NsdManager.PROTOCOL_DNS_SD, mDiscoveryListener);

第一个参数要和NSD服务器端定的ServerType一样.
第二个参数是固定的
第三个参数是扫描监听器

  1. 主动调用resolveService方法
nsdManager.resolveService(mmNsdServiceInfo, mResolverListener);

主动调用该方法,会触发ResolveListener(),从而获取到NsdServiceInfo信息。

  1. 需要停止时调用
nsdManager.stopServiceDiscovery(mDiscoveryListener);

6. 需要注意的点

(1)需要授予网络权限

 <uses-permission android:name="android.permission.INTERNET"/>

(2)服务发现是一项开销很大的操作,不使用时需要取消注册。不然很耗电。

(3)NsdServiceInfo对象

public void registerService(int port) {// Create the NsdServiceInfo object, and populate it.NsdServiceInfo serviceInfo = new NsdServiceInfo();// The name is subject to change based on conflicts// with other services advertised on the same network.serviceInfo.setServiceName("NsdChat");serviceInfo.setServiceType("_nsdchat._tcp");serviceInfo.setPort(port);}

此代码段将服务名称设置为“NsdChat”。此服务名称是实例名称:它是对网络上其他设备可见的名称。网络上使用 NSD 查找本地服务的任何设备都可以看到该名称。请记住,网络上任何服务的名称都必须是唯一的并且 Android 会自动处理冲突解决。如果网络中的两台设备都安装了 NsdChat 应用,则其中一台设备会自动更改服务名称,如更改为“NsdChat (1)”之类的。

第二个参数会设置服务类型,指定应用使用的协议和传输层。语法为“."。在代码段中,该服务使用通过 TCP 运行的 HTTP 协议。提供打印机服务(例如网络打印机)的应用会将服务类型设置为“_ipp._tcp”。

NsdServiceInfo类在Android 21 后,又引入了一个map的变量,可以设置键值对属性。官网对其的描述是如下:

/**
*将服务属性添加为键/值对。*服务属性包含为DNS-SD TXT记录对。*键必须是US-ASCII可打印字符,不包括“=”字符。值可以是UTF-8字符串或null。*key+value的总长度必须小于255字节。*键应该很短,最好不超过9个字符,并且每个NsdServiceInfo实例都是唯一的。用*同一个键调用setAttribute两次将覆盖第一个值。
*/
Add a service attribute as a key/value pair.Service attributes are included as DNS-SD TXT record pairs.The key must be US-ASCII printable characters, excluding the '=' character. Values may be UTF-8 strings or null. The total length of key + value must be less than 255 bytes.Keys should be short, ideally no more than 9 characters, and unique per instance of NsdServiceInfo. Calling setAttribute twice with the same key will overwrite first value.

可通过NsdServiceInfo中的 setAttributegetAttributes 两个方法来设置和获取键值对属性值。

tips:服务类型语法必须正确,不然注册不了。

六. 参考链接

官网文档

gittub的demo

Android基于NSD实现网络服务发现功能相关推荐

  1. android自带的nsd发现服务器,Android NSD(网络服务发现)是否与iOS中的Bonjour服务兼容?...

    I will create a server-less local networking App for iOS and Android. the App in both iOS and Androi ...

  2. android nsd和udp广播,Android网络服务发现(NSD)使用

    Android网络服务发现(NSD)使用 NSD(NsdManager)是Android SDK中自带的类库,可以集成直接使用. 使用 NSD服务需要(android4.1及以上) minSdkVer ...

  3. Android网络服务发现(NSD)协议的使用

    Android的网络服务发现协议(NSD)能够用于在小范围的网络中发现邻近设备上的某个应用.这对于一些社交网络.多人游戏类的应用会很有帮助. Android的NSD的用法大致上分为四种操作: 1. 注 ...

  4. android自带的nsd发现服务器,Android网络服务发现(NSD)协议的使用

    Android的网络服务发现协议(NSD)可以用于在小范围的网络中发现邻近设备上的某个应用.这对于一些社交网络.多人游戏类的应用会非常有帮助. Android的NSD的使用方法大致上分为四种操作: 1 ...

  5. android 发现服务,Android服务之网络服务发现服务

    自android 4.1 开始实现了一个网络服务的发现服务NsdService,其基于苹果的Bonjour服务发现协议,支持远程服务的发现和零配置. Bonjour协议包括IP地址的自动分配.服务名称 ...

  6. android p2p 连接服务器上,当通过Wi-Fi P2P使用网络服务发现时无法连接到Android设备每个人都可以使用网络服务发现...

    ! 我正在开发一个Android应用程序,允许与附近已安装此应用程序的设备聊天.为了做到这一点,我使用Wi-Fi P2P API和网络服务发现来搜索附近的设备. 我已经编写了用于在服务启动的线程中搜索 ...

  7. [享学Eureka] 一、源生Eureka介绍 --- 基于注册中心的服务发现

    凡事皆有代价,一切皆是取舍. 本专栏所有文章均计划逐步重写搬迁至本人公号:Java方向盘,且免费开放!故不再建议下单购买,可关注我公号前往免费学习.交流 –> 返回Netflix OSS套件专栏 ...

  8. Android官方开发文档Training系列课程中文版:连接无线设备之网络服务搜索功能

    原文地址:http://android.xsoftlab.net/training/connect-devices-wirelessly/index.html 引言 Android设备除了可以与服务器 ...

  9. android基于MVP小说网络爬虫、宝贝社区APP、仿虎扑钉钉应用、滑动阴影效果等源码...

    Android精选源码 android宝贝社区app源码 android仿Tinder最漂亮的一个滑动效果 android仿滴滴打车开具页,ListView粘性Header Android基于MVP模 ...

最新文章

  1. ffmpeg.exe 笔记
  2. 开源Registry项目Harbor源代码结构解析
  3. Android之back键拦截处理
  4. Modbus教程| Modbus协议,ASCII和RTU帧,Modbus工作
  5. PetShop之表示层设计
  6. ~~双链表(数据结构)
  7. Android Xfermode 实战 实现圆形、圆角图片
  8. 人工智能+智能运维解决方案_人工智能驱动的解决方案可以提升您的项目管理水平
  9. 无门槛福利:CSDN和文库下载
  10. nc文件的读取与写入
  11. App Extension应用扩展
  12. 搜索引擎算法大全-(百度+360+搜狗)
  13. 一个毕业设计 儿童趣味数学 app
  14. 当Facebook、谷歌等成为数据泄露大头时,它们如何改变?(上)
  15. Python使用selenium自动打开谷歌浏览器和网页
  16. TSC打印机ttp-247(java)
  17. 解密Google Deepmind AlphaGo围棋算法:真人工智能来自于哪里?
  18. marvell raid linux,MARVELL RAID管理软件操作演示
  19. 基于Winnow的中文邮件分类器的设计
  20. 晶振频率,时钟频率,时钟周期,时钟节拍,机器周期,指令周期的概念解析

热门文章

  1. crypto-js的使用
  2. 敏捷软件研发思想讲解
  3. 难忘的聚会,美好的时光(1957--1962)
  4. html滤镜菜鸟教程,Style
  5. 【同等学力申硕】在职研究生? 有用吗?
  6. 【VB6】如何用纯VB代码写个五子棋程序?(二)
  7. COSCon‘20 Track F 区块链论坛介绍
  8. Unity Hub许可证问题 达到最大申请次数之类的,Serial has reached the maximum number of activations
  9. 上海老大杜月笙——教你看穿一个人
  10. github 链接域名