Android NSD局域网发现服务
近期在了解局域网发现服务的时候无意间看到Android 自带的(Network Service Discovery)网络发现服务,在一番验证之后发现实现比较简单,可靠性也高,因此在这里做一个整理,算是对自己知识做一个归档。
网络服务发现(NSD)是一种机制,它允许设备在本地网络上相互发现并提供服务。在Android平台上,NSD API使得应用可以轻松地发现和注册网络上的服务。以下是NSD的一些关键点和如何在Android应用中使用它:
1.NSD的基本概念: NSD实现了基于DNS的服务发现(DNS-SD)机制,允许应用通过指定服务类型和名称来请求服务。这使得用户可以发现并连接到其他设备上运行的相同应用,适用于文件共享、多人游戏等点对点应用。
2.注册服务: 在本地网络上注册服务是可选的。如果需要注册服务,首先需要创建一个NsdServiceInfo对象,该对象提供了其他设备在决定是否连接到您的服务时所需的信息。服务名称是实例名称,对网络上的其他设备可见,且必须是唯一的。服务类型指定了应用使用的协议和传输层,例如_http._tcp表示通过TCP运行的HTTP协议,关于协议列表可以在该网页中查到: Service Name and Transport Protocol Port Number Registry 。
3.发现服务: 要发现网络上的服务,需要设置一个发现监听器,并调用discoverServices()方法。监听器会通知应用何时启动、何时发生故障,以及何时发现和丢失服务。
4.权限要求: 使用NSD服务需要在应用的AndroidManifest.xml文件中添加网络权限,如INTERNET权限。
5.示例代码: 代码中有完整的注释,这里就不再过多赘述。
注册服务的示例代码
public class NsdService implements NsdManager.RegistrationListener {private final NsdManager mNsdManager;/*** 自定义服务名称,该名称对局域网内使用NSD查找本地服务的设备可见。* 名称必须唯一,但是如果网络中有同名的服务,安卓系统会自动处理冲突,其中一个会被自动转换为类似MyService(1)这样的名称。*/private String mServiceName = "MyService";/*** 服务类型,即指定应用使用的协议和传输层。* 语法是“_< protocol >._< transportlayer >”,这里服务使用了TCP协议上的HTTP协议。* 想要提供打印服务(例如,一台网络打印机)的应用应该将服务的类型设置为“_ipp._tcp”。* 其他协议可以IANA中查看到:https://www.iana.org/assignments/service-names-port-numbers/service-names-port-numbers.xhtml*/private String mServiceType = "_http._tcp.";NsdService(Context context) {mNsdManager = (NsdManager) context.getSystemService(Context.NSD_SERVICE);}/*** 注册服务* @param port 网络服务的端口*/public void registerService(int port) {//创建了一个NsdServiceInfo 并传入端口、服务名称和协议NsdServiceInfo serviceInfo = new NsdServiceInfo();//这里是你要告诉发现端,你的网络服务的端口,可能是你的server socket的启动端口,切记非NSD的启动端口。serviceInfo.setPort(port);serviceInfo.setServiceName(mServiceName);serviceInfo.setServiceType(mServiceType);//注册NAS服务,此处最后一个参数是NsdManager.RegistrationListener监听mNsdManager.registerService(serviceInfo,NsdManager.PROTOCOL_DNS_SD,this);}@Overridepublic void onServiceRegistered(NsdServiceInfo NsdServiceInfo) {Log.d("NSD", "Service registered: " + NsdServiceInfo.getServiceName());}@Overridepublic void onRegistrationFailed(NsdServiceInfo serviceInfo, int errorCode) {Log.e("NSD", "Registration failed: Error code: " + errorCode);}@Overridepublic void onServiceUnregistered(NsdServiceInfo arg0) {Log.d("NSD", "Service unregistered");}@Overridepublic void onUnregistrationFailed(NsdServiceInfo serviceInfo, int errorCode) {Log.e("NSD", "Unregistration failed: Error code: " + errorCode);}
}
发现服务的示例代码
public class NsdDiscovery implements NsdManager.DiscoveryListener {private final NsdManager mNsdManager;/*** 服务类型,即指定应用使用的协议和传输层。* 语法是“_< protocol >._< transportlayer >”,这里服务使用了TCP协议上的HTTP协议。* 想要提供打印服务(例如,一台网络打印机)的应用应该将服务的类型设置为“_ipp._tcp”。* 其他协议可以IANA中查看到:https://www.iana.org/assignments/service-names-port-numbers/service-names-port-numbers.xhtml*/private String mServiceType = "_http._tcp.";NsdDiscovery(Context context) {mNsdManager = (NsdManager) context.getSystemService(Context.NSD_SERVICE);}//发现服务public void discoverServices() {//发现服务需要添加DiscoveryListener监听,关于发现服务所有的信息会在该回调内通知mNsdManager.discoverServices(mServiceType,NsdManager.PROTOCOL_DNS_SD,this);}@Overridepublic void onStartDiscoveryFailed(String serviceType, int errorCode) {Log.e("NSD", "Discovery start failed: Error code: " + errorCode);}@Overridepublic void onStopDiscoveryFailed(String serviceType, int errorCode) {Log.e("NSD", "Discovery stop failed: Error code: " + errorCode);}@Overridepublic void onDiscoveryStarted(String serviceType) {Log.d("NSD", "Service discovery started");}@Overridepublic void onDiscoveryStopped(String serviceType) {Log.d("NSD", "Discovery stopped: " + serviceType);}/*** 网络内发现了服务* @param serviceInfo*/@Overridepublic void onServiceFound(NsdServiceInfo serviceInfo) {Log.d("NSD", "Service discovery success " + serviceInfo);//检查服务的类型,确认这个类型我们的应用是否可以接入。if (!serviceInfo.getServiceType().equals(mServiceType)) {Log.d("NSD", "Unknown Service Type: " + serviceInfo.getServiceType());}//比较找到服务的名称与本地服务的名称,判断设备是否获得自己的(合法的)广播。else if (serviceInfo.getServiceName().contains("MyService")) {//如果是自己的服务,需要再进一步解析服务端的信息,包括IP和端口。mNsdManager.resolveService(serviceInfo, new ResolveListener());}}@Overridepublic void onServiceLost(NsdServiceInfo serviceInfo) {Log.e("NSD", "service lost" + serviceInfo);}private class ResolveListener implements NsdManager.ResolveListener {@Overridepublic void onResolveFailed(NsdServiceInfo serviceInfo, int errorCode) {Log.e("NSD", "Resolve failed" + errorCode);}//解析完成之后通知@Overridepublic void onServiceResolved(NsdServiceInfo serviceInfo) {Log.d("NSD", "Resolve Succeeded. " + serviceInfo);// 连接到服务端的代码//...}}
}
不要忘记添加权限
<uses-permission android:name="android.permission.INTERNET" />
相关文章:
Android NSD局域网发现服务
近期在了解局域网发现服务的时候无意间看到Android 自带的(Network Service Discovery)网络发现服务,在一番验证之后发现实现比较简单,可靠性也高,因此在这里做一个整理,算是对自己知识做一个归档。 网络服…...
算法的学习笔记—左旋转字符串(牛客JZ58)
😀前言 在程序设计中,字符串处理问题屡见不鲜,其中“字符串左旋”是一种常见操作,今天我们一起来探讨一个经典的左旋转字符串题目,以及一种优雅的解决方案——三步翻转法。 🏠个人主页:尘觉主页…...
Mac 上无法烧录 ESP32C3 的问题记录:A fatal error occurred:Failed to write to target RAM
文章目录 问题描述驱动下载地址问题解决:安装 CH343 驱动踩的坑日志是乱码 问题描述 我代码编译可以,但是就是烧录不上去 A fatal error occurred:Failed to write to target RAM(result was 01070000:Operation timed out) Uploaderror:上传失败&…...
ios 项目升级极光SDK
由于项目使用的是旧版本,隐私合规检查不通过,需要升级到最新版本, 使用cocoapods集成无法正常运行,.a文件找不到,可能项目比较久了,最好选择手动导入 下载最新版本SDK,将 SDK 包解压ÿ…...
【Java】java | logback日志配置 | 按包配置级别
一、概述 日志配置需求: 本地部分包开debug,其他路径走配置;只在本地环境有效 二、logback.xml配置 <!--本地调试,开debug--> <springProfile name"dev"><logger name"cn.hg.demo" level&quo…...
Virtuoso使用layout绘制版图、使用Calibre验证DRC和LVS
1 绘制版图 1.1 进入Layout XL 绘制好Schmatic后,在原理图界面点击Launch,点击Layout XL进入版图绘制界面。 1.2 导入元件 1、在Layout XL界面左下角找打Generate All from Source。 2、在Generate Layout界面,选中“Instance”&#…...
Spring框架原理面试题及参考答案
目录 什么是Spring 开发框架? 说说Spring 的 IOC 和 DI? 简述IoC(控制反转)及在 Spring 中的实现 说说Spring IOC 容器的基本概念? 说说Spring IoC 的实现机制? 说说Spring IoC 容器? 简述Spring ApplicationContext 说说Spring Bean 的生命周期 说说在 Spring…...
Java类的static成员以及代码块(详细版)
文章目录 一、什么是static成员二、static修饰的成员有何意义三、static修饰成员变量四、static修饰成员方法4.1、静态成员变量不可以在方法内创建4.2、静态成员方法内部不可以访问非静态成员变量4.3、总结 五、static成员变量的初始化5.1、就地初始化5.2、静态代码块初始化 六…...
Opensearch集群部署【docker、服务器、Helm多种部署方式】
操作系统兼容性 我们建议在 Red Hat Enterprise Linux (RHEL) 或使用systemd的基于 Debian 的 Linux 发行版上安装 OpenSearch ,例如 CentOS、Amazon Linux 2 和 Ubuntu Long-Term Support (LTS)。OpenSearch 应该适用于大多数 Linux 发行版,但我们只测…...
本地Docker部署开源WAF雷池并实现异地远程登录管理界面
💝💝💝欢迎来到我的博客,很高兴能够在这里和您见面!希望您在这里可以感受到一份轻松愉快的氛围,不仅可以获得有趣的内容和知识,也可以畅所欲言、分享您的想法和见解。 推荐:kwan 的首页,持续学…...
性能需求笔记
名称解释 系统用户:所有注册过的用户;在线用户:某时间段内登录且在线的用户 pv:用户浏览页面的次数 UV:登录系统的用户,uv课产生多个pv 性能测试:测试软件在系统中的运行性能,度量系…...
ts:数组的常用方法(reduce累加)
ts:数组的常用方法(reduce累加) 一、主要内容说明二、例子reduce方法(累加)1.源码1 (reduce方法)2.源码1运行效果 三、结语四、定位日期 一、主要内容说明 ts中数组的reduce方法,用…...
Begin
cpp 编程的发展方向还是很多的:游戏、嵌入式、QT、客户端、服务端、机器学习、算法大模 型 ...,现阶段还是不太清楚具体想走什么方向。主QT编程应该是不在考虑之内的,可以为辅简单 学习一下;游戏方向:需要学习lua语言…...
【实战案例】Django框架表单处理及数据库交互
本文基于之前内容列表如下: 【图文指引】5分钟搭建Django轻量级框架服务 【实战案例】Django框架基础之上编写第一个Django应用之基本请求和响应 【实战案例】Django框架连接并操作数据库MySQL相关API 【实战案例】Django框架使用模板渲染视图页面及异常处理 更新编…...
python开发工具是选择vscode还是pycharm?两款软件优缺点对照!
Pycharm和VSCode是两款流行的代码编辑器,它们都有各自的优缺点和适用情况。本文将从以下几个方面对它们进行比较和分析: 功能和扩展性性能和稳定性用户体验和界面价格和支持 功能和扩展性 Pycharm是一款专为Python开发而设计的集成开发环境(…...
2025选题|基于Hadoop的物品租赁系统的设计与实现
作者简介:Java领域优质创作者、CSDN博客专家 、CSDN内容合伙人、掘金特邀作者、阿里云博客专家、51CTO特邀作者、多年架构师设计经验、多年校企合作经验,被多个学校常年聘为校外企业导师,指导学生毕业设计并参与学生毕业答辩指导,…...
【Qt】QTableView添加下拉框过滤条件
实现通过带复选框的下拉框来为表格添加过滤条件 带复选框的下拉框 .h文件 #pragma once #include <QCheckBox> #include <QComboBox> #include <QEvent> #include <QLineEdit> #include <QListWidget>class TableComboBox : public QComboBox …...
部署DNS主从服务器
一。DNS主从服务器作用: DNS作为重要的互联网基础设施服务,保证DNS域名解析服务的正常运转至关重要,只有这样才能提供稳定、快速日不间断的域名查询服务 DNS 域名解析服务中,从服务器可以从主服务器上获取指定的区域数据文件&…...
从可逆计算看低代码
2020年低代码(LowCode)这一buzzword频繁亮相于主流技术媒体,大背景下是微软/亚马逊/阿里/华为等巨头纷纷入场,推出自己的相应产品。一时之间,大大小小的技术山头,无论自己原先是搞OA/ERP/IOT/AI的ÿ…...
设计模式最佳实践代码总结 - 结构型设计模式篇 - 侨接设计模式最佳实践
目录 侨接设计模式最佳实践 侨接设计模式最佳实践 桥接模式是一种结构型设计模式,它将抽象部分与它的实现部分分离,使它们可以独立地变化。桥接模式是一种结构型设计模式,它将抽象部分与它的实现部分分离,使它们可以独立地变化。…...
.Net框架,除了EF还有很多很多......
文章目录 1. 引言2. Dapper2.1 概述与设计原理2.2 核心功能与代码示例基本查询多映射查询存储过程调用 2.3 性能优化原理2.4 适用场景 3. NHibernate3.1 概述与架构设计3.2 映射配置示例Fluent映射XML映射 3.3 查询示例HQL查询Criteria APILINQ提供程序 3.4 高级特性3.5 适用场…...
uni-app学习笔记二十二---使用vite.config.js全局导入常用依赖
在前面的练习中,每个页面需要使用ref,onShow等生命周期钩子函数时都需要像下面这样导入 import {onMounted, ref} from "vue" 如果不想每个页面都导入,需要使用node.js命令npm安装unplugin-auto-import npm install unplugin-au…...
Mybatis逆向工程,动态创建实体类、条件扩展类、Mapper接口、Mapper.xml映射文件
今天呢,博主的学习进度也是步入了Java Mybatis 框架,目前正在逐步杨帆旗航。 那么接下来就给大家出一期有关 Mybatis 逆向工程的教学,希望能对大家有所帮助,也特别欢迎大家指点不足之处,小生很乐意接受正确的建议&…...
关于iview组件中使用 table , 绑定序号分页后序号从1开始的解决方案
问题描述:iview使用table 中type: "index",分页之后 ,索引还是从1开始,试过绑定后台返回数据的id, 这种方法可行,就是后台返回数据的每个页面id都不完全是按照从1开始的升序,因此百度了下,找到了…...
cf2117E
原题链接:https://codeforces.com/contest/2117/problem/E 题目背景: 给定两个数组a,b,可以执行多次以下操作:选择 i (1 < i < n - 1),并设置 或,也可以在执行上述操作前执行一次删除任意 和 。求…...
Python如何给视频添加音频和字幕
在Python中,给视频添加音频和字幕可以使用电影文件处理库MoviePy和字幕处理库Subtitles。下面将详细介绍如何使用这些库来实现视频的音频和字幕添加,包括必要的代码示例和详细解释。 环境准备 在开始之前,需要安装以下Python库:…...
MySQL用户和授权
开放MySQL白名单 可以通过iptables-save命令确认对应客户端ip是否可以访问MySQL服务: test: # iptables-save | grep 3306 -A mp_srv_whitelist -s 172.16.14.102/32 -p tcp -m tcp --dport 3306 -j ACCEPT -A mp_srv_whitelist -s 172.16.4.16/32 -p tcp -m tcp -…...
以光量子为例,详解量子获取方式
光量子技术获取量子比特可在室温下进行。该方式有望通过与名为硅光子学(silicon photonics)的光波导(optical waveguide)芯片制造技术和光纤等光通信技术相结合来实现量子计算机。量子力学中,光既是波又是粒子。光子本…...
基于 TAPD 进行项目管理
起因 自己写了个小工具,仓库用的Github。之前在用markdown进行需求管理,现在随着功能的增加,感觉有点难以管理了,所以用TAPD这个工具进行需求、Bug管理。 操作流程 注册 TAPD,需要提供一个企业名新建一个项目&#…...
站群服务器的应用场景都有哪些?
站群服务器主要是为了多个网站的托管和管理所设计的,可以通过集中管理和高效资源的分配,来支持多个独立的网站同时运行,让每一个网站都可以分配到独立的IP地址,避免出现IP关联的风险,用户还可以通过控制面板进行管理功…...
