目录
法律声明
本文档中包含的信息均得到了Creative Commons Attribution-ShareAlike 3.0 Unported License的许可。(i)本文档中的所有源代码都是基于Apache License version 2.0授权;(ii)本文档和包含的所有信息都是基于“as-is”申明,并且没有任何形式的担保。
AllJoyn是高通创新中心公司的商标,其它产品和品牌可以注册或使用其各自所有者的注册商标。
这种技术数据可能受制于美国和国际的出口、转口或转让法律。严禁违反美国或国际法律。
Qualcomm Innovation Center, Inc. (高通创新中心公司)
5775 Morehouse Drive
San Diego, CA 92121-1714
U.S.A.
Copyright © 2011, Qualcomm Innovation Center, Inc., All rights not expressly granted are reserved.
HT80-BA013-1 Rev B
可能包含美国和国际出口控制信息
前言
目的
本文档提供了AllJoyn™的高层次介绍。它描述了系统的总体目标和优势,以及AllJoyn如何在移动环境下提高网络体验。此外,该文档涵盖了系统和描述在高层次的基本抽象,以及多个AllJoyn系统是如何工作并提供基于相邻的点对点(peer-to-peer)移动计算环境的。
范围
该文档专门提供给对使用AllJoyn系统来提升网络或分布式手机应用性能感兴趣的人。我们假设使用者对移动通信技术并不特别擅长,所以该文档对于任何对peer-to-peer网络感兴趣的人都是适合的,包括应用开发商、系统软件开发者、网络专家、设备制造商和产品经理。
修订历史
下表提供了本文档的修订历史。
表1.修订历史 | ||
版本 | 日期 | 描述 |
A | June 22, 2011 | Initial release |
B | November 22, 2011 | Formatting changes only |
概述
AllJoyn是一个开放源码的软件系统,它为分布式应用程序在不同设备中提供了运行环境,特别是移动性、安全性和动态配置。AllJoyn系统处理了异构分布式系统中固有的难题,并解决了将移动性引入方程时所产生的独特问题。这使得应用开发人员可以将注意力集中到应用程序的核心问题上了。
AllJoyn是一个“中性平台”,它被设计为相对于它运行的具体操作系统、硬件和设备尽可能的独立。事实上,AllJoyn是在Microsoft Windows、Linux和Android三种环境中开发出来的。
AllJoyn始终秉承相邻性和移动性的设计理念。在移动环境下,设备将不断与其它的相邻设备连接和断开,并可以改变底层网络能力。
AllJoyn作为一个开源项目遵守Apache Version 2.0 license授权。AllJoyn的代码库可以从http://www.alljoyn.org上获取。
AllJoyn技术适用的应用程序类型只会受制于开发者的想象力。扩展社交网络就是其中一个例子。用户可以在配置文件中记录自己的喜好和兴趣。当进入其它位置后,具有这种AllJoyn功能的手机就会立即寻找附近其它具有类似兴趣的设备,并创建一个点对点的对等设备之间的通信网络,让它们进行沟通和信息交换。
现在,大多数手机都集成了蓝牙功能,所以如果两个人处在同一个房间并开启了蓝牙,AllJoyn可以允许手机之间直接进行沟通,并允许应用程序进行交互(如果AllJoyn的安全系统允许)。例如,如果两个用户进入一个拥有Wi-Fi热点的家庭或办公室,他们的设备可以连接到底层接入点并充分利用额外的网络容量。此外,他们的设备还可以查找到邻近的其它设备(Wi-Fi的覆盖区域中),发现这些设备上的服务,如果需要的话还能使用这些服务。
使用AllJoyn实现的另一个例子就是实时多玩家游戏。图1显示了如何使用不同设备和不同底层网络技术来实现多用户游戏。基础设备的详细管理都由AllJoyn处理,所以游戏作者可以把重点放在游戏的设计和开发上,而不是解决对等网络的复杂性。
图1. AllJoyn异构网络
作为AllJoyn生态系统的扩展,你可以想象出丰富多彩的应用。例如:
Ÿ 创建一个音乐播放列表,将它们输入具有AllJoyn功能的汽车音响系统,或储存到家用立体声系统中(受数字版权管理)
Ÿ 当你刚从国外或旅行后回到家中,同步最新的照片或者其它媒体到启用了AllJoyn功能的数字相框或电视中
Ÿ 控制家电产品如电视机、录像机和游戏机
Ÿ 笔记本电脑和台式电脑的互动,并在该区域中分享内容
Ÿ 企业中的同事之间或学校中的学生之间进行项目协作
Ÿ 提供基于邻近发放的电子优惠券或名片服务
可能性是无穷无尽的。
AllJoyn的优势
如前所述,AllJoyn是一个中性平台系统,旨在简化邻近异构分布式移动通信网络系统。这里的异构性不仅表示不同的设备,而且可以是具有不同操作系统和不同类型的设备(例如个人电脑、手机、平板电脑和消费性电子产品),并且使用不同的通信技术。
开源
AllJoyn是在Apache Version 2.0 license授权下作为一个开源项目进行开发的。这代表所有的AllJoyn代码库都是可供查阅的,并且鼓励开发者进行补充和改进。如果AllJoyn缺少某个功能,你可以对此作出改进和贡献。如果你在嵌入式设备中使用AllJoyn,或者有任何技术性问题,我们开源社区中的众多参都会愿意提供帮助和指导。AllJoyn的代码库可以在http://www.alljoyn.org中获得。
操作系统的独立性
AllJoyn提供了一个抽象层,允许AllJoyn及其应用程序运行在多个操作系统平台上。AllJoyn支持大部分的标准Linux发行版本包括Ubuntu等,并可以运行在Android 2.2和更高版本的智能手机和平板设备上。AllJoyn还在常见版本的Microsoft Windows操作系统上进行了测试和验证,包括Windows XP和Windows7。
开发语言的独立性
目前,开发人员可以使用C++或Java语言来创建应用程序。其它语言的支持也将很快面世。
物理网络和协议的独立性
现在,网络设备支持许多的通信技术。AllJoyn提供了一个抽象层,它为底层网络协议栈定义了统一的接口,使得软件工程师可以相对容易地添加和安装新的网络。
最近,Wi-Fi联盟发布了一个Wi-Fi Direct规范,这将允许点对点的Wi-Fi连接。并且Wi-Fi Direct的网络硬件模块也正在积极开发中,它将为AllJoyn开发者增加Wi-Fi Direct功能和可用网络选项的预关联发现机制。
动态配置
通常情况下,移动设备在使用过程中会到达不同的地点,并不断与各种网络进行连接和断开。这意味着它的IP(互联网协议)地址可能会改变,网络接口可能无法使用,服务可能是短暂性的。
AllJoyn可以获知当前服务的断开和新服务的出现,并创建新的连接(如果需要)。AllJoyn准备作为Wi-Fi Hotspot 2.0技术的应用层,这种技术旨在提升手机和信号发射塔对Wi-Fi热点的漫游透明度。
有些情况下,网络拓扑结构对分布式应用程序的性能至关重要。蓝牙网络配置成微微网会比配置成分布式网络达到更好的性能。AllJoyn在内部对这些配置进行管理,而不需要开发人员对每种网络技术的具体特性进行任何了解。
广播和发现服务
当设备需要交互时,必须进行某种形式的广播和发现服务。在静态网络的时代,人作为管理员对设备之间通信作出了精确的安排。最近,零配置网络的概念已经得到了普及,尤其是苹果的Bonjour和微软的Plug and Play技术。我们也看到,现有技术的发现机制如蓝牙服务发现协议,和新兴机制如Wi-Fi Direct P2P发现规范。而AllJoyn提供了一种广播和发现服务的抽象,可以简化定位和应用服务的流程。
安全
分布式应用程序中安全性的固有模型是应用程序到应用程序的。不幸的是,在许多情况下,网络安全模型并不匹配这种固有的协定。例如,蓝牙协议就要求必须在设备之间进行配对。使用这种方法,一旦设备配对成功,两个设备上的所有应用程序都会得到授权。但是当考虑更多比蓝牙耳机更强大的设备时,这就不可取了。例如,两台笔记本电脑通过蓝牙进行连接,那么更精细的安全控制是非常有必要的。AllJoyn在设计上对这种复杂的安全模型提供了广泛的支持,特别是应用程序到应用程序的通信。
对象模型和远程方法调用
AllJoyn采用了一种易于理解的对象模型和远程方法调用(RMI)机制。AllJoyn重新实现了总线协议,基于D-BUS规范和扩展D-BUS协议,以支持分布式设备。
软件组件
根据标准的对象模型和总线协议可以规范各种接口组件。Java接口声明提供的一个与本地实现实例进行交互的规范,也采用了大致相同的方式。AllJoyn对象模型中提供了一个独立于语言的规范,来实现远程交互。
规范中考虑了多种接口的实现,从而可以支持应用程序通信的标准定义。这对于软件组件是可以实现的技术。软件组件已经成为了许多现代系统的核心部分,例如Android系统,它定义了四个主要的组件类型作为与Android应用框架进行交互的唯一渠道;或者在微软系统中,它使用了组件对象模型(COM)系统的子节点。
我们期待出现丰富的接口定义,以实现概述一节中描述的情景。AllJoyn项目希望与用户进行合作,共同定义和公布标准接口支持,并实现共享。
概念概述
AllJoyn中包含了许多抽象概率,以帮助理解并将各个部分联系在一起。你只需要掌握少数关键的抽象以了解基于AllJoyn的系统。
本节提供了了解AllJoyn的更高层次的视角,和后续文件(如详细的API文档)的基础。
远程方法调用
分布式系统就是一组自主计算机通过某种形式的网络通信来实现一个共同的目标。如果希望运行在某台机器地址空间中的程序去调用位于另一台物理机器地址空间中的进程。这通常需要通过远程过程调用(RPC),如果使用了面向对象的概念,那么就需要通过RMI或远程调用(RI)。
在RPC交换的基本模型中,涉及到作为RPC发送者的客户端(client),和实际执行所需远程过程的服务器(server),在AllJoyn中称为service。发送者执行一个客户端存根,看起来就像是本地系统上的本地进程。客户端存根将进程的参数包装(称为编组或参数序列)成某种形式的消息,然后由RPC系统调用,并使用一些标准传输机制进行消息传递,如传输控制协议(TCP)。在远程机器上,需要运行相应的RPC系统来解组(反序列化)参数并将消息传递到服务器存根中安排执行所需的进程。如果调用的进程需要返回任何信息,将采用类似的过程把返回值传递到客户端存根,最后返回原来的发送者。
请注意它并不要求给定的进程在执行中必须独占客户端或服务器。如果两个或多个进程在相同的客户端或服务器中执行,它们将被认为是并行的。许多情况下,AllJoyn应用程序将执行类似的功能,而且被认为是并行。AllJoyn既支持原始的客户端和服务功能,也支持对等网络。
AllJoyn总线
AllJoyn系统最基本的抽象就是AllJoyn总线。它为分布式系统提供了一个快速、轻量级的方式来传递消息序列。你可以将AllJoyn总线看作是消息传递的“高速公路”。图2显示了单一设备上AllJoyn总线实例在理论上的结构。总线用加粗的水平黑线表示。垂直线可以被认为是消息通过总线在源点和目的点之间传递的“出口”。
图2所示的总线连接被描述为了六边形(这是任意选择的形状)。正如高速公路的出口通常都具有编号,图中每个连接都分配了唯一的连接名称。为了清晰起见,这里使用连接名称的简化形式。
许多情况下,总线上的连接都可以被认为是进程的合作方。因此,在图2的例子中,独特的连接名称:1.1可能被分配给应用程序实例进程的一个连接,而独特的连接名称:1.4可能被分配给其它应用程序实例进程的连接。AllJoyn总线的目标就是让两个应用程序进行通信,而无需处理底层机制的细节。其中一个连接可以认为是客户端存根,另一方就可以认为是服务器存根。
图2. 典型的AllJoyn总线
图2显示了AllJoyn总线的一个实例,说明了软件总线如何给连接到总线上的组件提供进程间通信。AllJoyn总线的典型设备扩展如图3所示。组件可根据需要,在Smartphone和Linux主机上的组件之间创建逻辑总线段之间的通信链路。
图 3. AllJoyn处理设备到设备的通信
通信链路的管理由AllJoyn系统负责,并且由许多底层技术组成,例如Wi-Fi和蓝牙技术。可能有不同的设备参与管理AllJoyn总线,但是这对分布式总线上的用户都是透明的。对于总线上的某个组成部分,分布式AllJoyn系统看起来就像是本地设备中的总线。
图4显示了分布式总线对于总线上的用户是如何呈现的。一个组件(例如,智能手机连接的名称为1.1)可以创建一个进程来调用Linux主机上的名称为1.7的组件,而无需担心该组件的物理位置。
图4. 分布式AllJoyn总线类似一条本地总线
总线守护进程
图3说明了逻辑分布式总线实际上被分成了若干个段,每个段都运行在不同的设备上。AllJoyn从功能上实现这些逻辑总线段的进程被称为AllJoyn守护进程。
Unix派生系统中的长驻守护进程,通常用来描述运行在计算机系统中并提供一些必要功能的程序。在Windows系统中,长驻服务更加常见,但是我仍然是指AllJoyn在Windows系统中的守护进程。
图5. 总线的相关气泡图形
为了让AllJoyn守护进程更形象化,我们创建气泡图是很有用的。考虑两段AllJoyn总线,一段位于Smartphone上而另一段位于Linux主机,如图5所示。总线连接被标记为了客户端(C)和服务器(S)基于RMI模型。执行分布式总线核心的守护进程被标记为(D)。图5中的组件通常被解释为如图6所示的插图。
图6. AllJoyn气泡图形
气泡可以被看作分布式系统上运行的计算机进程。左侧的两个客户端(C)和一个服务(S)进程运行在Smartphone上。这三个进程与Smartphone上的AllJoyn守护进程通信,实现了分布式AllJoyn总线上的本地网段。在右侧,也有一个守护进程,它在Linux主机上实现了AllJoyn总线的本地网段。这两个守护进程将协调整个逻辑总线的消息流,如图4所示,逻辑总线是单一的实体连接。类似Smartphone中的配置,Linux主机上有两个服务组件和一个客户端组件。
在此配置中,客户端组件C1可以采用远程方法来调用服务组件S1,就像它是一个本地对象。参数在源头进行封装,并由Smartphone上的守护进程送至本地总线段的路由。封装参数通过网络链接(从客户端来看是透明的)发送至Linux主机上的守护进程。而Linux主机上运行的守护进程确定目的地是S1,并且对封装参数进行拆封,然后通知服务去调用远程方法。如果有返回值,那么将反向进行这个通信过程,把返回值传回给客户端。
由于守护进程在后台运行,并且客户端和服务都运行在单独的进程中,所以在每个单独进程中必须有一个守护进程的“代理”。 AllJoyn将调用这些代理总线附件。
总线附件
每个AllJoyn总线连接都需要一个特定的AllJoyn组件作为介质,它称为总线附件。每个需要连接AllJoyn总线的进程都有一个总线附件。
当在硬件和软件之间讨论软件组件时,往往会引出一个比喻。我们可以将分布式AllJoyn总线的本地网段想象为台式电脑的底板硬件总线。硬件总线本身就能传递电子信息,并且有一个可以插卡的点称为连接器。AllJoyn中类似功能的连接器就是总线附件。
AllJoyn总线附件是本地指定语言的对象,它代表了分布式AllJoyn总线中的客户端、服务或对等点。例如,这里有为用户提供总线附件功能的C++语言实现,还有为用户提供相同总线附件功能的Java语言实现。由于AllJoyn增加了语言支持,将会有更多这样的具体语言实现。
总线方法、总线属性和总线信号
AllJoyn基本上是一个面向对象的系统。在面向对象的系统中,人们将谈论对象中的调用方法(因此对于分布式系统,人们将谈论长驻远程方法调用)。面向对象编程中的对象需要有成员。通常,还需要对象方法或属性,在AllJoyn中就是BusMethods和BusProperties。AllJoyn同样也有总线信号(BusSignal),它是对象中某些事件或状态变化的异步通知。
为了使客户端、服务和对等点之间的通信更加透明,那么总线方法和总线信号中的参数顺序必须有一些规范,并且总线属性中也必须有一些形式的类型信息。对于计算机科学,方法(或信号)输入和输出类型的申明或定义被称为类型签名。
类型签名使用字符串来定义,包括所有的基本数字类型(对于大多数编程语言),以及从这些基本类型创建出的复合类型,例如数组和结构体。类型签名的具体分配和使用超出了本文介绍的范围,但是总线方法、信号或属性的类型签名将传递给AllJoyn底层系统,来实现总线上传递参数和封装返回值的转换。
总线接口
在大多数面向对象的编程系统中,方法或属性集合将合并到具备固有内在联系的群组中。该集合函数的统一申明被称为接口。接口为执行接口规范的实体与外界之间的连接提供服务。正因为如此,接口需要适当的标准结构来实现标准化。各种网站上可以找到众多的接口服务规范,从电话到媒体播放器控制。D-Bus规范在XML中进行描述来指定接口。
接口规范会将总线方法、总线信号、总线属性以及与它们相关的类型签名组合到一个命名组中。而实际上,接口会由客户端、服务或对等点进程来实现。如果实现了给定的命名接口,那么在这个实现和外界之间会有一个隐性契约,接口将会支持它所有的总线方法、总线信号和总线属性。
接口名称通常采用域名反转形式。例如,这里有许多AllJoyn实现的标准接口。其中有一个标准接口是theorg.alljoyn.Businterface,将守护实现并为总线附件提供一些基本功能。
值得注意的是,接口名称仅仅是相对自由形式的命名空间中的一个字符串,并且其它命名空间可能也有类似的外观。接口名称字符串提供的特定函数不应该和其它类似的字符串混淆,特别是总线名称。例如,org.alljoyn.sample.chat可能是总线名称常量,就是客户端搜索的名字。但是也有可能org.alljoyn.sample.chat是接口名称,它定义了总线对象采用特定的总线名称连接到总线附件上时提供的方法、信号和属性。如果存在给定接口名称的接口就暗示了总线名称的存在;但是,它们确实是两个完全不同的东西,有时可能长得一模一样。
总线对象和对象路径
总线接口提供了一种标准的方式来声明分布式系统中的接口。总线对象提供桥接到可能实现给定接口规范的地方。总线对象存在于总线附件中,并作为通信的终点。
因为,在特殊的总线附件中特定的接口可能会有多种实现,所以必须增加额外的结构体来区分这些接口实现。这将由对象路径来提供。
就像接口名称是命名空间中的一个字符串,对象路径同样也存在于命名空间中。命名空间的结构就像一棵树,路径的思维模式就是文件系统的目录树。事实上,对象路径的路径分隔符使用的是斜杠字符,和Unix文件系统类似。由于总线对象是总线接口的实现,所以对象路径可以遵循相应接口的命名约定。如果定义了一个磁盘控制器接口(exampleorg.freedesktop.DeviceKit.Disks),那么你就可以想象,对于同一系统中的两个分开的物理磁盘,这个接口的不同实现应该遵循下面的对象路径:
/org/freedesktop/DeviceKit/Disks/sda1
/org/freedesktop/DeviceKit/Disks/sda2
代理总线对象
AllJoyn总线上的总线对象需要通过代理访问。代理就是通过总线访问远程对象的本地代表。代理是非常常见的,而且不限于AllJoyn系统,但是你经常会在AllJoyn的内容中看到ProxyBusObject,它表明了代理的具体性质――这是一个远程总线对象的本地代理。
ProxyBusObject是AllJoyn底层代码中的一部分,它提供了对象代理的基本功能。
通常,RMI系统的目标就是提供一个代理来实现接口,它看起来就像是需要调用的远程对象。代理对象实现了和远程对象相同的接口,但是要驱动封装参数的过程和向服务发送数据。
在AllJoyn中,客户端和服务软件,往往要与具体的编程语言绑定,来提供实际用户级的代理对象。这个用户级的代理对象使用AllJoyn代理总线对象的能力,以实现本地/远程透明的目标。
总线名称
AllJoyn总线上的连接作为一个服务,提供接口名称描述的接口实现。接口实现被加入到服务总线对象的树中。客户端希望通过代理对象获得服务,并且使用底层AllJoyn代理总线对象来进行总线方法、总线信号和总线属性相关信息在逻辑AllJoyn总线上的传递。
为了拥有完整的总线地址图,总线上的连接必须具有唯一的名称。AllJoyn系统将会为每个总线附件分配一个唯一的临时总线名称。但是,这种唯一的名称在服务每次连接到总线是都会自动生成,因此并不适合作为持久的服务标识符。在服务连接到总线时必须有一种连续和持久的方法。这些持久的名称被称为“well-known names”。
正如使用域名来指向互联网上的主机系统,它不会随着时间而改变(例如quicinc.com),你可以使用它们的well-known总线名称指向AllJoyn总线的功能单元。正如接口名称采用域名反转形式,总线名称也有相同的形式。注意,这是造成某些混淆的根源,因为为了方便,接口名称和well-known总线名称往往选择相同的字符串。请记住它们为了不同的目的:接口的名称,是为了标识出总线附件中总线对象执行的客户端和服务之间的合约;而well-known名称标识了一个服务,它提供了一种持久的方式实现客户端和附件之间的连接。
使用well-known名字,应用程序(总线附件的方式)必须向总线守护进程请求使用该名称。如果这个well-known名称没有被其它应用占用,那么理所当然可以使用它。因此,在任何时候任何情况下,well-known名称都会确保在总线上代表唯一的地址。
通常well-known名称就意味着总线附件与总线对象以及一些可用的服务概念之间实现了连接。因为总线名称在分布式总线上提供了唯一的地址,它们必须保证在总线上是唯一的。例如,你可以使用总线名称org.alljoyn.sample.chat,这表明相同名称的总线附件正在执行聊天(chat)服务。如果它已经采用了这个名字,你就可以推断它在总线对象中实现了相应的org.alljoyn.sample.chat接口,对象路径位于/org/alljoyn/sample/chat。
它的问题是,为了实现“聊天”,你一定希望在AllJoyn总线上发现其它类似的组件,并且也支持聊天服务。由于总线名称必须唯一地标识总线附件,因此就需要追加一些后缀的形式来确保它的唯一性,你可以采用用户名或数字的形式。在聊天的例子中,我们可以假象出多个总线附件:
org.alljoyn.sample.chat.bob
org.alljoyn.sample.chat.carol
在这个例子中,well-known名称将org.alljoyn.sample.chat.作为了服务名称的前缀,从中可以推断出聊天接口和对象实现的存在。后缀bobandcarol可以使well-known名称实例是唯一的。
这将引出服务是如何在分布式系统上定位的问题。答案就是通过客户端的服务广播和发现。
广播和发现
服务广播和发现的问题有两个方面。如上所述,即使服务驻留在本地AllJoyn总线段上,你也需要能够看见和检查总线上所有总线附件的well-known名称,以确定其中某个对具体服务感兴趣。当考虑如何发现非现有总线段上的服务时,将产生一个更有趣的问题。
让我们想想如果一台运行AllJoyn的设备进入了另一台的邻近区域时可能会发生什么。由于两台设备实现了物理隔离,所涉及的两个总线守护进程都没有办法获取对方的任何信息。那么守护进程是如何确定对方的存在,以及如何确定是否需要互相连接形成一条逻辑分布式AllJoyn总线呢?
答案就是通过AllJoyn服务的广播和发现功能。当服务在本地设备上启动后,它会保留指定的well-known名称,然后向邻近设备广播它的存在。AllJoyn提供了一个抽象层,它使服务可以完成广播操作,并且能通过底层技术,例如Wi-Fi、蓝牙、Wi-Fi Direct,来实现透明通信。无论客户端或者服务都不需要了解底层技术是如何管理这些广播的。
例如,在接触交换(contacts-exchanging)应用中,应用的一个实例可以保留well-known名称org.alljoyn.sample.contacts.boband,并广播这个名称。这可能会产生下面的一个或多个结果:通过连接Wi-Fi接入点的UDP组播,Wi-Fi Direct的预关联服务广播,或蓝牙的服务发现协议消息。广播者并不需要关注其中的广播通信机制。由于接触交换应用理论上是一个点对点的应用,人们期望另一个电话也进行类似的服务广播,例如org.alljoyn.sample.contacts.carol。
客户端应用程序可能会通过初始化发现操作,来在接收广播时宣布它的兴趣。例如,它可能会指定前缀org.alljoyn.sample.contacts来请求发现接触服务的实例。在这种情况下,两个设备都会发出这样的请求。
只要手机进入了其它设备的邻近范围,底层AllJoyn系统就会通过可选的传输协议来发送和接收广播消息。它们都将自动接收到一个指示,表面相应的服务可用。
由于服务广播可以通过多个传输协议来接收,在某些情况下,它需要额外的底层工作来确定底层通信机制,这是使用发现服务的另一个概念部分。这是通信会话。
会话
此前已经讨论了总线名称、对象路径和接口名称的概念。当一个实体连接到AllJoyn总线时,它会被分配一个唯一的名称。连接(总线附件)请求被授予一个well-known名称。well-known名称用来让客户端定位或发现总线上的服务。例如,某个服务可能连接到AllJoyn总线上并被总线分配了唯一的名称:1.1。如果服务希望总线上的其它实体能够发现它,这个服务就必须向总线请求well-known名称,例如com.companyA.ProductA(记住,通常要附加上唯一的实例修饰符)。
这个名称意味着至少有一个实现well-known接口的总线对象是有意义的。通常,总线对象使用连接实例来鉴别,通过与well-known名称相同的组件路径(这并不是要求,仅仅是一个约定)。在这个例子中,总线对象的路径与总线名称com.companyA.ProductA匹配,可能是/com/companyA/ProductA。
为了了解从客户端总线附件到类似的服务附件的通信会话是如何形成的,并提供一个端到端的例子,把AllJoyn机制和更常见的机制进行比较和对比是非常有用的。
邮政地址模拟
在AllJoyn中,服务要求具有一个“人类可读”的名字,这样它就可以使用这个well-known和易于理解的标签来进行广播了。well-known名称必须被底层网络翻译成唯一的名称来提供正确的路由信息,例如:
Well-known-name:org.alljoyn.sample.chat
唯一名称::1.1
这些信息告诉我们,广播到总线附件中的well-known名字org.alljoyn.sample.chat已经被指定了唯一的名称:1.1。你可以认为这种方式就像每个企业都有一个名称和邮政地址一样。
另一种比喻,当大楼里面的一个企业与其它企业发生业务联系时,也是相同的状况。在这种情况下,你可能会先找一组房间号然后再进一步确定公司的地址。由于AllJoyn总线附件能够提供多个服务,还必须有一种方法在特定的附件中确定一个以上的目标。在邮政地址模拟中还需要在目的地址组号之后添加“连接端口号”。
这正如一个国家的邮件系统或私人快递公司根据快件不同的紧迫程度(当天件、两天件、陆路运送等)发送一封信件。当使用AllJoyn进行连接服务时,你必须指定出某些特定需要的网络连接的特点,并提供一套完整的传递规范(例如,可靠地传递信息、可靠地传递非结构化数据、不可靠地传递非结构化数据)。
请注意,在上面的例子中地址信息和传递信息是分开的。就像你可以选择几种路线将一封信从一个地方传递到另一个地方,很明显,你也可以使用AllJoyn系统从几个路径获得传递的数据。
AllJoyn会话
正如正确标记的邮政信件具有“寄件(from)”和“收件(to)”地址,AllJoyn会话同样要求“from”和“to”信息。在AllJoyn系统中,“from”地址将对应客户端组件的位置,而“to”地址对应服务的位置。
从技术上讲,这些计算机网络环境中“from”或“to”地址被称为半连接。在AllJoyn中,这些to(服务)地址有下列形式:
{session options(会话选项), bus name(总线名称), session port(会话端口)}
第一个参数会话选项,涉及到如何将数据从连接的一侧传输到其它地方。在IP网络中,选项可能是TCP或UDP。在AllJoyn中,这些细节是抽象的,所有选项可以是“基于消息的”、“非结构化数据”或“不可靠的非结构化数据”。服务目标是通过总线附件请求的well-known名称指定的。
和邮政例子中的组号类似,AllJoyn也具有总线附件内部传输点的概念。在AllJoyn中,这被称为会话端口。正如组号仅仅代表在给定的大楼中,会话端口同样表示在给定的总线附件范围内。连接端口的存在和值是从总线名称中推断出来的,与底层对象和接口集合的推断使用了相同的方式。
“from”地址对应的客户信息同样也会形成。为了与服务进行通信,客户端必须具有它自己的半连接。
{session options(会话选项), unique name(唯一名称), session ID(会话ID)}
它并不要求客户端请求well-known总线名称,所以它们提供其唯一的名称(如:1.1)。由于客户端并不作为会话的目的地,所以它们不提供会话的端口,但在建立连接时会被分配一个会话ID。此外,在会话建立过程中,将会给服务返回一个会话ID。对于那些熟悉TCP网络的开发者,这就相当于TCP中使用的连接创建过程,其中服务是通过well-known端口进行的连接。当连接建立后,客户端会使用临时端口来描述一个类似的半连接。
在会话建立的过程中,这两个半连接会有效地组合:
{session options, bus name, session port} 服务
{session options, unique name, session ID} 客户端
请注意,会话选项有两种实现。当开始建立通信时,它们可能被视为服务提供的支持会话选项和客户端提供的服务与请求会话选项。会话的建立过程还包括磋商会话中实际将使用的选项。一旦会话已经形成,在客户端和服务端的半连接就被描述为唯一的AllJoyn通信路径:
{session options(会话选项), bus name(总线名称), unique name(唯一名称), session ID(会话ID)}
在会话建立过程中,将在通信守护进程之间形成一个逻辑网络连接。这可能需要创建一个蓝牙微微网或其它复杂的拓扑结构管理操作。如果这样的连接已经存在,它将被重新启用。新创建的底层“守护进程-守护进程”的连接将用于执行初始安全检查,一旦这个操作完成后,这两个守护进程就已经有效地加入了两个独立的AllJoyn软件总线段以及更大的虚拟总线中。
因为考虑到端到端的底层连接流量控制的问题,在一些技术中会关注拓扑平衡问题,实际两个通信端的连接(“from”客户端和“to”服务)可能会或可能不会形成一个单独的通信通道。在某些情况下,最好是通过ad-hoc拓扑结构来传递消息(蓝牙微微网),而另一些情况下,直接通过新的连接来传递消息可能是更好的选择(TCP IP)。这里可能需要对通信基础技术具有深刻的理解,而AllJoyn会很高兴为你完成这些。用户只需要知道消息会根据传输机制选择正确的路由,以满足应用程序的抽象需求。
综述
AllJoyn旨在提供一个软件总线用于管理广播操作和发现服务,提供安全的环境,并且允许位置透明的远程方法调用。可以采用传统的客户端/服务模型,也可以采用结合客户端和服务两方面的对等通信。
AllJoyn最基本的抽象就是把所有东西连接在一起的软件总线。虚拟分布式总线是通过每台设备上运行的后台AllJoyn守护进程来实现的。客户端和服务通过总线附件连接到总线。总线附件位于本地的客户端和服务进程中,并且提供与本地AllJoyn守护进程的进程间通信。
在连接时,每个总线连接都会被系统分配唯一的名称。总线附件可以要求获得唯一的“人类可读”的总线名称,它可以用来向AllJoyn系统的其余部分广播它自己。这个命名空间中的well-known总线名称看起来就像反转的域名,并鼓励命名空间的自我管理。如果存在指定名称的总线附件,那么意味着至少有一个总线对象,它实现了至少一个名称指定的接口。接口名称被分配给相似的命名空间,但是与总线名称具有不同的意义。每个总线对象都位于总线附件的树形结构体中,并且描述了一个看着类似Unix文件系统路径的对象路径。
图7显示所有部件连接方式的假想布局。中间的黑线代表AllJoyn总线。总线的出口就是指定了唯一名称(:1.1和:1.4)的总线附件。在图中,具有唯一名称(:1.1)的总线附件被以org.alljoyn.samples.chat.1进行请求,并分配相应的well-known总线名称。添加“1”以确保总线的名称是唯一的。
总线名称中还暗示了很多信息。首先,总线对象的树形结构体驻留在不同的路径中。在下面的例图中,有两个总线对象。一个是在“/org/alljoyn/samples/chat/chat”路径下,它大概实现了一个聊天界面。其它总线对象在“/org/alljoyn/samples/chat/contact”路径下,实现了名为org.alljoyn.samples.chat.contacts的接口。由于给定的总线对象实现了接口,它必须提供相应的总线方式、总线信号和总线属性的实现。
图7. AllJoyn总线实例图示
数字42代表了一个连接会话端口,客户端必须使用它初始服务的通信会话。请注意,这个会话仅相对于特定的总线附件是唯一的,图中的其它总线附件也可以使用42作为自己的连接端口。
在请求和分配well-known总线名称之后,服务通常会广播它的名称来让客户端发现这个服务。图8显示了服务向本地守护进程发送广播请求。守护进程根据服务的输入,决定应该采用网络中的某种具体机制来进行广播,并开始执行操作。
图8. 服务执行广播操作
当准客户端希望定位一个服务时,它会发出查询名称的请求。其本地守护设备,再从客户端输入的基础上,确定最佳的方式来查询和探测广播。
图9. 客户端请求查询名称
一旦设备移动到邻近区域中,它们就会开始监听对方的广播消息和发现请求通过启用的媒体。图10显示守护进程是如何驱动服务来监听发现请求和响应的。
图10. 守护进程报告发现名称
最后,图11显示了客户端收到的指示,表面该区域发现一个新出现的承载了所需服务的守护进程。
图11. 客户端发现服务
发展方案中的客户端和服务双方都使用总线附件对象的方法和回调,以请求协调广播和发现过程。服务端要求总线对象提供服务,并且客户端希望使用代理对象提供一个易于使用的接口与服务进行通信。此代理对象将使用AllJoyn ProxyBusObject来协调与服务的通信,并提供方法参数和返回值的封装和拆封处理。
通信会话必须在远程方法被调用前被创建,以有效地加入不同的总线段。广播和发现与会话的建立并不相同。终端可以接收广播并不采取任何行动。只有当接收到广播,并且客户端决定加入通信会话时,总线才会从逻辑上连接为一体。要做到这一点,服务必须建立通信会话端点并广播它的存在;客户端必须接收这些广播,并要求加入会话中。
服务必须在广播它的服务之前定义一个半连接。对它进行抽看起来像是下面这样:
{reliable IP messages(可靠的IP消息), org.alljoyn.samples.chat.1, 42}
这表明它将通过可靠的消息传输与客户端通信,已经指定了well-known总线名称,并且预计连接到会话端口42。这是图7中看到的情况。
假设总线附件具有唯一的名称:2.1,并希望从远程物理设备的守护进程进行连接。它将向系统提供半连接,然后会分配一个新的会话ID来让通信双方进行沟通:
{reliable IP messages, org.alljoyn.samples.chat.1, :2.1, 1025}
新的通信会话将使用可靠的消息传递协议来实现,它采用IP协议栈在名为org.alljoyn.samples.chat.1(服务)的总线附件和名为:2.1(客户端)的总线附件之间进行通信。用来描述会话的会话ID是系统分配的,在这种情况下是1025。
作为建立的端到端的通信会话,AllJoyn系统采取的任何操作都是为了更好地创建虚拟软件总线,如图4所示。请注意这是一张模拟的图片,而实际中可能发生的是,通过TCP连接建立了一个Wi-Fi Direct的点对点连接,使用无线接入点承载UDP连接,或蓝牙微微网组成L2CAP连接,决定于所提供的会话选项。无论是客户端还是服务,我们都为它们完成了这些非常困难的工作。
如果需要,也可以要求进行身份验证,接着客户端和服务会使用RMI模型进行通信。
当然,这并不限于一台设备上的一个客户端和另一台设备上的一个服务。而可能是任何数量的客户端和任何数量的服务(不能超过设备或网络容量的限制)相结合,以实现某种形式的协同工作。总线附件可能需要掌握客户端和服务的属性来完成点对点服务。AllJoyn守护进程建立了许多不同组件和消息路由的管理逻辑单元。此外,接口描述和语言绑定的性质可以允许不同编程语言编写的组件之间的互操作性。
高层系统架构
从用户的角度来看AllJoyn系统,了解架构最重要的一块就是客户端、服务或对等点。从系统的角度来看,三个基本用例之间确实也没有差异,仅仅是系统提供的相同功能的不同使用模式。
客户端、服务和对等点
图12显示了用户角度(守护进程)的系统架构。在最高层级是语言绑定。AllJoyn系统是使用C++编写的,所以对于这种语言的使用者就不需要进行绑定了。但是,对于其它语言如Java或JavaScript的用户,就会提供相对轻量级的转换层称为语言绑定。在某些情况下,绑定可被扩展到提供指定系统的支持。例如,普通的Java语言绑定将允许AllJoyn系统可以在Windows或Linux下运行的一般Java环境中使用;但是,也可以提供Android系统绑定,将AllJoyn系统更加紧密地集成到指定的Android结构中,例如Android应用框架中的服务组件。
系统和语言绑定是建立在一个辅助对象层上,设计它的目的就是为了让AllJoyn系统中常见的操作更容易。不使用这些辅助对象也可以操作AllJoyn系统,但是我们鼓励使用它,因为它提供了另一个层次的抽象接口。前面章节中提到的总线附件,就是这样一种重要的辅助对象,它在所有的系统中都是可用的。除了提供的几个关键功能,总线附件还提供非常方便的功能,使对底层软件总线的管理和互动更容易。
在辅助层之下是消息和路由层。它们的主要功能是负责对总线发送的消息中的参数和返回值进行封装和解封。路由层安排将消息传递到适当的总线对象和代理,并安排其它总线附件的接收消息被发送到总线守护进程。
消息和路由层与端点层进行通信。在较低层的AllJoyn系统中数据从一个端点传送到另一个。从网络代码的角度来说这是抽象的通信端点。网络抽象全部在端点层的顶部,所以通过蓝牙连接和通过有线以太网连接之间基本上没有差异。
图12. 基本的客户端、服务或对等点架构
端点专指传输机制的具体实体,它提供了基本的网络功能。在客户端、服务或对等点的情况下,网络传输的唯一渠道就是本地传输。这是与本地AllJoyn总线守护进程之间的本地进程间通信。在基于Linux的系统中,这是一个Unix域套接字连接,而在基于Windows的系统中,这是一个和本地守护进程的TCP连接。
AllJoyn还提供了操作系统抽象层,它提供了建立系统其余部分的平台,并且在最底层就是本机系统。
守护进程
AllJoyn守护进程就像胶水一样将各个AllJoyn系统连接到一起。如前所述,守护进程在后台运行,等待相关事件的触发并响应它们。因为这些事件通常是外部的,那么最好从自下而上的角度来接近守护进程架构。
在图13中的最底层就是本机系统。我们使用和客户端架构中相同的操作系统抽象层,来为Linux,Windows和Android上运行的守护进程提供共同的抽象。我们有守护进程的各种底层网络组件运行在操作系统抽象层上。由于客户端、服务和对等点只使用本地进程间通信机制与守护进程进行通信,所以守护进程就必须处理给定平台上的各种可用传输机制。注意,图13中的“本地(Local)”传输是运行在特定主机上的AllJoyn客户端、服务和对等点的基础连接。
图13. 基本守护进程架构
蓝牙传输处理了蓝牙系统中的微网的创建和管理的复杂性。此外,蓝牙传输还提供了适当的蓝牙服务广播和发现功能,以及提供了可靠的通信。
有线、Wi-Fi和Wi-Fi Direct传输都在IP下被分组,因为所有这些传输都使用底层的TCP-IP网络协议栈。如何完成服务广播和发现有时具有显著的差异,因为该功能在TCP-IP标准范围之外,所以有模块专门支持这个功能。
各种特定技术的传输实现都被聚合到网络传输抽象中。会话模块将处理通信连接的建立和保持,使守护进程和其相关的客户端、服务和对等点集合为一个统一的软件总线。
AllJoyn守护进程使用端点的概念来提供与本地客户端、服务和对等点的连接,而且将这些对象扩展为“总线-总线”的连接,它可以被守护进程用于主机到主机的消息传输。
除了这些连接所隐含的路由功能,AllJoyn守护进程还提供了其总线对象相应端点管理或控制守护进程实现的软件总线段。例如,当一个服务请求广播well-known总线名称时,实际上是服务中的辅助对象将这个请求转换为远程方法调用,并指向守护程序实施的总线对象。和服务的情况类似,守护进程有许多总线对象位于相关的对象路径,来实现特定名称的接口。控制AllJoyn总线的底层机制,就是向这些守护进程的总线对象发送远程方法调用。
守护进程操作的某些方面的整体操作都由配置子系统进行控制。这允许系统管理员指定系统中的某些权限,并提供按需创建服务的能力。此外,守护进程配置也可以限制资源消耗,例如,允许系统管理员限制任何特定时间的活跃TCP连接的数量。还有选项可以允许系统管理员降低某些拒绝服务攻击的影响,通过限制目前登陆的连接数。
总结
AllJoyn是一个综合系统,设计用来为移动异构系统上的分布式应用程序提供一个部署的框架。
AllJoyn提供的解决方案基于成熟的技术和标准的安全系统,使用连贯、系统的方式解决各种网络技术的相互作用。这使得应用开发人员可以专注于他们的应用程序内容,而不需要具备丰富的底层网络开发经验。
AllJoyn系统被设计为一个整体来工作,并不会出现例如使用各个部分创建ad-hoc系统时遇到的固有阻抗不匹配的问题。我们相信,AllJoyn系统可以使分布式应用程序的开发和部署比在其它平台上开发要简单很多。
了解更多
要了解更多有关如何在你的开发工作中整合AllJoyn的信息,请访问AllJoyn网站中的文档(https://www.alljoyn.org/docs-and-downloads)。
入门指南:此章节中的文档描述了AllJoyn的技术和概念。
Ÿ AllJoyn介绍
开发指南:开发指南提供了具体编程问题的解决方案,和搭建开发环境的指南。还包括了代码片段与注释。
Ÿ AllJoyn Android环境安装指南
Ÿ 使用Java SDK进行AllJoyn开发的指南
Ÿ AllJoyn Android的C + +示例程序攻略
Ÿ 配置生成环境(Microsoft Windows平台)
Ÿ 配置生成环境(Linux平台)
API参考手册:API参考手册提供了详细的AllJoyn源代码,和使用各种支持的编程语言编写的应用程序。
Ÿ Java API参考手册
Ÿ C++ API参考手册
下载:为用户提供软件开发工具包(SDK)和示例代码,以帮助建立、修改、测试和执行指定任务。
Ÿ AllJoyn SDK示例代码(包括AllJoyn守护进程)