Android的网络服务发现协议(Net service discovery,基于mDNS),网络服务发现 (NSD) 可让您的应用访问其他设备在本地网络上提供的服务。支持 NSD 的设备包括打印机、网络摄像头、HTTPS 服务器以及其他移动设备。
NSD 实现了基于 DNS 的服务发现 (DNS-SD) 机制,该机制允许您的应用通过指定服务类型和提供所需类型服务的设备实例的名称来请求服务。Android 和其他移动平台均支持 DNS-SD。
将 NSD 添加到应用中,可让您的用户识别本地网络上是否有其他设备支持您的应用所请求的服务。这对于各种点对点应用非常有用,例如文件共享或多人游戏。Android 的 NSD API 简化了实现此类功能所需的工作。
Android的NSDManager提供了两个关键类:NsdServiceInfo 和 NsdManager。
NsdManager包含了以下操作
1. 注冊网络服务
通过该接口对外发布网络服务
public void registerService (NsdServiceInfo serviceInfo,
int protocolType,
NsdManager.RegistrationListener listener)
2. 发现网络服务
通过该接口可以实时监听网络服务的上线与下线
public void discoverServices (String serviceType,
int protocolType,
NsdManager.DiscoveryListener listener)
3. 匹配网络服务
通过该接口获取感兴趣的网络服务,并实现连接
public void resolveService (NsdServiceInfo serviceInfo,
NsdManager.ResolveListener listener)
4. 反注册网络服务
public void unregisterService (NsdManager.RegistrationListener listener)
5.停止扫描网络服务
public void stopServiceDiscovery (NsdManager.DiscoveryListener listener)
典型的网络协议接口列表,可以通过这个链接找到
https://www.iana.org/assignments/service-names-port-numbers/service-names-port-numbers.xml
以下是android nsdmanager的接口原型,通过这个nsdmanager api demo,你可以快速实现一个网络服务发布,发现和匹配例子。
首先注册网络权限
发布网络服务
NsdServiceInfo nsdServiceInfo = new NsdServiceInfo();
nsdServiceInfo.setAttribute("key0", "value0");
int port = startServer();
nsdServiceInfo.setServiceName("local-test-net");
nsdServiceInfo.setServiceType(SERVICE_TYPE);
nsdServiceInfo.setPort(port);
try {
nsdManager.registerService(nsdServiceInfo, NsdManager.PROTOCOL_DNS_SD, mListener);
} catch (Exception e) {
e.printStackTrace();
}
扫描网络服务
nsdManager.discoverServices(SERVICE_TYPE, NsdManager.PROTOCOL_DNS_SD, new NsdManager.DiscoveryListener() {
@Override
public void onStartDiscoveryFailed(String s, int i) {
Log.d(TAG, "onStartDiscoveryFailed: " + s + "," + i);
}
@Override
public void onStopDiscoveryFailed(String s, int i) {
Log.d(TAG, "onStopDiscoveryFailed: " + s + "," + i);
}
@Override
public void onDiscoveryStarted(String s) {
Log.d(TAG, "onDiscoveryStarted: " + s);
}
@Override
public void onDiscoveryStopped(String s) {
Log.d(TAG, "onDiscoveryStopped: " + s);
}
@Override
public void onServiceFound(NsdServiceInfo nsdServiceInfo) {
Log.d(TAG, "onServiceFound: " + nsdServiceInfo);
Log.d(TAG, "\t --> : " + nsdServiceInfo.getHost() + ", " + nsdServiceInfo.getAttributes());
}
@Override
public void onServiceLost(NsdServiceInfo nsdServiceInfo) {
Log.d(TAG, "onServiceLost: " + nsdServiceInfo);
}
});
匹配网络服务,并连接服务
NsdServiceInfo nsdServiceInfo = new NsdServiceInfo();
nsdServiceInfo.setServiceName("local-test-net");
nsdServiceInfo.setServiceType(SERVICE_TYPE);
nsdManager.resolveService(nsdServiceInfo, new NsdManager.ResolveListener() {
@Override
public void onResolveFailed(NsdServiceInfo nsdServiceInfo, int i) {
Log.d(TAG, "onResolveFailed: " + nsdServiceInfo + ", " + i);
}
@Override
public void onServiceResolved(NsdServiceInfo nsdServiceInfo) {
Log.d(TAG, "onServiceResolved: " + nsdServiceInfo + ", " + nsdServiceInfo.getHost().getHostAddress());
try {
Socket socket = new Socket(nsdServiceInfo.getHost().getHostAddress(), nsdServiceInfo.getPort());
} catch (IOException e) {
e.printStackTrace();
}
Toast.makeText(getApplicationContext(), "connect server ok", Toast.LENGTH_LONG).show();
}
});
当运行起来后,如果无法实时获取相邻的设备实时发布的服务,因为还需要增加网络多播的权限,
源码下载地址