Android组播域名服务

Multicast DNS is a way of using familiar DNS programming interfaces, packet formats and operating semantics, in a small network where no conventional DNS server has been installed.

上文是来自http://www.multicastdns.org/的说明

1.1Bonjour背景介绍

Bonjour是法语中的Hello之意。它是Apple公司为基于组播域名服务(multicast DNS)的开放性零配置网络标准所起的名字。使用Bonjour的设备在网络中自动组播它们自己的服务信息并监听其它设备的服务信息。设备之间就像在打招呼,这也是该技术命名为Bonjour的原因。Bonjour使得局域网中的系统和服务即使在没有网络管理员的情况下也很容易被找到。

Bonjour技术在Mac OS以及Itunes、Iphone上都得到了广泛应用。为了进一步推广,Apple通过开源工程mdnsresponder将其开源出来。在Windows平台上,它将生成一个后台程序mdnsresponder。在Android平台上(或者说支持POSIX的Linux平台)它是一个名为mdnsd的程序。

我们重点需要了解android平台的mdnsresponder。

图一


1.2Bonjour用处

一个简单的例子:在局域网中,如果要进行打印服务,必须先知道打印服务器的IP地址。此IP地址一般由IT部门的人负责分配,然后他还得全员发邮件以公示此地址。有了Bonjour以后,打印服务器自己会依据零配置网络标准在局域网内部找到一个可用的IP并注册一个打印服务,名为“print service”之类的。当客户端需要打印服务时,会先搜索网络内部的打印服务器。由于不知道打印服务器的IP地址,客户端只能根据诸如"print service"的名字去查找打印机。在Bonjour的帮助下,客户端最终能找到这台注册了“print service”名字的打印机,并获得它的IP地址以及端口号。

从Bonjour角度来看,该技术主要解决了三个问题:

·Addressing:即为主机分配IP。Bonjour的Addressing处理比较简单,即每个主机在网络内部的地址可选范围内找一个IP,然后查看网络内部是否有其他主机再用。如果该IP没有被分配的话,它将使用此IP。

·Naming:Naming解决的是host名和IP地址的对应关系。Bonjour采用的是Multiple DNS技术,即DNS查询消息将通过UDP组播方式发送。一旦网络内部某个机器发现查询的机器名和自己设置的一样,就回复这条请求。此外,Bonjour还拓展了MDNS的用途,即除了能查找host外,还支持对service的查找。不过,Bonjour的Naming有一个限制,即网络内部不能有重名的host或service。

·Service Discovery:SD基于上面的Naming工作,它使得应用程序能查找到网络内部的服务,并解析该服务对应的IP地址和端口号。应用程序一旦得到服务的IP地址和端口号,就可以直接和该服务建立交互关系。

下面我们将介绍BonjourAPI中使用最多的三个函数,它们分别是服务注册、服务查询和服务解析。理解这三个函数的功能也是理解mdns的基础。

Android对应的代码为external/mdnsresponder/mDNSShared/dns_sd.h

服务注册的API为DNSServiceRegister,原型如图所示:

图二

该函数的解释如下:

·sdRef:代表一个未初始化的DNSService实体。其类型DNSServiceRef是指针。该参数最终由DNSServiceRegister函数分配内存并初始化。

·flags:表示当网络内部有重名服务时的冲突处理。默认是按顺序修改服务名。例如要注册的服务名为“printer”,当检测到重名冲突时,就可改名为“printer(1)”。

·interfaceIndex:表示该服务输出到主机的哪些网络接口上。值-1表示仅对本机支持,也就是该服务的用在loop接口上。

·name:表示服务名,为空的话就取机器名。

·regtype:服务类型,用字符串表达。Bonjour要求格式为"_服务名._传输协议",例如"_ftp._tcp"。目前传输协议仅支持TCP和UDP。

·domian和host一般都为空。

·port表示该服务的端口。如果为0的话,Bonjour会自动分配一个。

·txtLen以及txtRecord字符串用来描述该服务。一般都设置为空。

·callBack:设置回调函数。该服注册的请求结果都会通过它回调给客户端。

·context:上下文指针,由应用程序设置。

当客户端需要搜索网络内部特定服务时,需要使用DNSServiceBrowserAPI,其原型如图2所示:

图三

其中:

·sdref、interfaceIndex、regtype、domain以及context含义与DNSServiceRegister一样。

·flags:在本函数中没有作用。

·callBack:为DNSServiceBrowser处理结果的回调通知接口。

当客户端想获得指定服务的IP和端口号时,需要使用DNSServiceResolveAPI,其原型如下图所示:

其中:

·name、regtypedomain都从DNSServiceBrowse函数的处理结果中获得。

·callBack用于通知DNSServiceResolve的处理结果。该回调函数将返回服务的IP地址和端口号。

1.3Android Says Bonjour

Android平台的Bonjour架构可由下图图表达:

图四

由上图可知,Android拓展了原有的Bonjour架构,改变如下:

·在Netd中增加了MDnsSdListener对象,它一方面通过socket和framework上层对象通信,另一方面通过Bonjour API和mdnsd通信(也是基于Socket的跨进程通信)。从mdnsd角度来看,它是最懂Bonjour API的”人“了。

·System_process进程新增NsdService。Nsd是Network Service Discovery的缩写。NsdService通过socket和位于Netd中的MDnsSdListener通信。

·App借用NsdManager API通过Binder技术和System_process的NsdService通信。

1.3.1MDnsSdListener介绍

MDnsSdListener在Android Bonjour架构中扮演着转换器的角色:

·一方面它处理来自framework 上层NsdService的请求,并通过Bonjour API将其转换成mdnsd能懂的“语言”以驱动其工作。

·另一方面它接收来自mdnsd的信息,并把它们通报给NsdService。

在系统中该代码在Netd中,system/netd/MDnsSdListener.cpp。

由上图可知:

·MDnsSdListener的内部类Monitor用于和mdnsd进程通信,它将调用前面提到的Bonjour API。

·Monitor内部针对每个DNSService都会建立一个Element对象,该对象通过Monitor的mHead指针保存在一个list中。

·Handler是MDnsSdListener注册的Command。

下面将简单介绍MDnsSdListener的运行过程,其主要工作可分成三步:

·Netd创建MDnsSdListener对象,其内部会创建Monitor对象,而Monitor对象将启动一个线程用于和mdnsd通信,并接收来自Handler的请求。

·NsdService启动完毕后将向MDnsSdListener发送"start-service"命令。

·NsdService响应应用程序的请求,向MDnsSdListener发送其他命令,例如"discovery"等。Monitor将最终处理这些请求。

·Monitor的threadStart线程将调用其run函数,该函数通过poll方式侦听包括mCtrlSocketPair在内的socket信息。

·当NsdService发送"start-service"命令后,Handler的runCommand将执行Monitor的startService函数。

starService将启动mdnsd,如下面代码所示:

MDS_SERVICE_NAME宏代表字符串"mdnsd",property_set("ctl.start",MDNS_SERVICE_NAME);这个方法是android启动service独特的方式,可以在device目录init.rc下找到该定义mdnsdf服务:

当NsdService发送注册服务请求时,Handler的serviceRegister函数将被调用,代码如下所示

DNSServiceRegister内部将把请求发送给mdnsd去处理,处理的结果通过MDnsSdListenerRegisterCallback返回,该函数最终会通过socket把信息传递给NsdService去处理。

1.3.2NsdService介绍

对所有Android App来说,就是通过NsdService来实现自己的服务。

图9列出了NsdService中的几个重要成员,其中:

·NsdService从INsdManager.stub派生。这个类也是Android的特色产品,由INsdManager.aidl文件生成。

·NsdService内部工作将通过NsdStateMachine及内部的三个状态对象(DefaultState、EnableState、DisableState)驱动。

·NsdService通过NativeDaemonConnector和Netd中的MDnsSdListener建立socket通信。

mNativeConnector = newNativeDaemonConnector(new NativeCallbackReceiver(), "mdns", 10,MDNS_TAG, 25);

通过socketname(mdns)跟MDnsSdListener通信,其中这个socketname在device/rockchip/rksdk/init.rc文件定义:

service netd /system/bin/netd

class main

socket netd stream 0660 root system

socket dnsproxyd stream 0660 root inet

socket mdns stream 0660 root system

·类NativeCallbackReceiver用来通知NsdService来自Netd的消息。

·NsdService中的NsdServiceInfo,它就是Network Service在Android Bonjour中的代表。其包含的内容有服务名、服务类型、IP地址和端口号等。

·类NativeCallbackReceiver用来通知NsdService来自Netd的消息。

·NsdService中的NsdServiceInfo,它就是Network Service在Android Bonjour中的代表。其包含的内容有服务名、服务类型、IP地址和端口号等。

1.3.3NsdChat案例介绍

Android SDK新增了一个NsdChat例子用于向开发者介绍Android平台中Nsd的使用方法。相关文档位于http://developer.android.com/training/connect-devices-wirelessly/nsd.html。案例的源码位于Android4.4源码根目录/development/samples/training/NsdChat下。

该例描述了一个简单的聊天程序,故其命名为NsdChat。Nsd在此例中的作用就是注册并搜索网络内的聊天服务。

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 193,968评论 5 459
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 81,682评论 2 371
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 141,254评论 0 319
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 52,074评论 1 263
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 60,964评论 4 355
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 46,055评论 1 272
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 36,484评论 3 381
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 35,170评论 0 253
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 39,433评论 1 290
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 34,512评论 2 308
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 36,296评论 1 325
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 32,184评论 3 312
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 37,545评论 3 298
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 28,880评论 0 17
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 30,150评论 1 250
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 41,437评论 2 341
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 40,630评论 2 335

推荐阅读更多精彩内容

  • Android 自定义View的各种姿势1 Activity的显示之ViewRootImpl详解 Activity...
    passiontim阅读 171,042评论 25 707
  • Spring Cloud为开发人员提供了快速构建分布式系统中一些常见模式的工具(例如配置管理,服务发现,断路器,智...
    卡卡罗2017阅读 134,490评论 18 139
  • 好久没更了,终于又能更画了 这回用了10支左右画完这样一副画,彩铅好不好真的很重要!颜色叠加最麻烦,感觉给我再多的...
    你说的我都相信阅读 252评论 0 3
  • 《茧》by 张悦然 在一次出行的火车上看完了书的前三章,那个时候程恭还没有发现祖辈的秘密,仇恨还没有延续。李佳栖的...
    吴无物阅读 1,446评论 1 1
  • 阿莲 给日子一点色彩,是有意思的事啊!我不刻意做一个旅行者,在自己的小窝里,也可以云游四海,室雅兰香,读我们自己的...
    骄阳下的一朵莲阅读 144评论 0 2