原文连接:https://allseenalliance.org/developers/learn/core/standard-core
AllJoyn框架是一个开源软件系统,提供一个在不同设备类型上运行分布式应用的环境,它着重强调移动性,安全性和动态配置。AllJoyn系统处理异构分布式系统中固有的疑难问题,并解决添加移动性后出现的一些特殊问题。这可以让开发人员专注于他们正在构建应用的核心问题,。
AllJoyn框架是“平台无关”的,这意味着它在设计之初就要求:尽可能独立操作系统,硬件,以及设备上运行的软件。事实上,现在AllJoyn架构可以运行在Microsoft Windows,Linux和Android,iOS,OS X,OpenWRT,也可以作为Unity游戏开发生态系统中的Unity插件。
AllJoyn框架被设计为重点关注“周边,附近”和“移动性”。在移动环境中,设备将不断地进入和离开的其他设备周边,同时底层网络环境也可能会发生变化。
AllJoyn SDKs 可以在链接中获得 (http://www.allseenalliance.org).
框架的应用程序类型只会受开发者想象力的限制。扩展社交网络就是一个例子。用户定义好自己的喜好和利益,到达一个地方后,具有AllJoyn功能的手机会立刻发现附近其他具有同样爱好的设备,在设备间建立通信网络,让它们可以沟通并交换信息。
现在手机基本都集成了Wi-Fi,所以如果两个用户走进一个有Wi-Fi热点的家庭或办公室,他们的设备可以连接到接入点,享受额外的网络性能。此外,他们的设备可以定位邻近(Wi-Fi覆盖范围内)的其它设备,可以发现其它设备上的额外服务,并使用这些服务(如果需要的话)。另外,有可能使用混合拓扑连接,这样采取AllJoyn精简核心库的设备可使用蓝牙作为传输方式。一旦连接到运行AllJoyn框架的设备,它可以和Wi-Fi设备上的应用进行交互。
实现实时多玩家游戏可能是AllJoyn框架应用场景的另一例子。例如,多用户游戏可以使用不同的设备类型,如笔记本电脑,平板电脑和手机;也可能使用不同的底层网络技术,如Wi-Fi。基础设施管理的细节由AllJoyn架构都处理,让游戏开发者专注于游戏的设计和执行,而不用关注点对点网络的复杂性。
随着AllJoyn生态系统的扩展,我们可以想到很多应用。例如:
· 创建音乐播放列表,同步歌曲到支持AllJoyn的汽车音响系统,或将它们存储在家里的音响系统中(受数字版权管理)
· 旅行回来后,同步照片或其他媒体数据到支持AllJoyn的数码相框或电视
· 控制家用电器,如电视机,数字录像机,或游戏机
· 在笔记本和台式机之间进行互动和内容分享
· 同事和学生在企业和教育环境之间的项目协作
· 提供基于邻近性的服务,如派发优惠券或电子名片
如前所述,AllJoyn架构是一个平台无关系统,旨在简化邻近异构分布式系统移动通信网络。
这里的异构(Heterogeneous)不仅意味着不同的设备,还意味着不同类型的设备(例如,个人电脑,手机,掌上电脑,消费性电子产品),运行着不同的操作系统,使用不同的通信技术。
AllJoyn框架作为一个开源项目进行开发。这意味着所有的AllJoyn代码都可供查阅,并鼓励开发者贡献补充和增强。如果AllJoyn框架缺少一个功能,你可以加入进来作出自己的贡献。如果您使用AllJoyn框架时碰到障碍,或有技术问题,在开源社区中其他参与者准备并愿意提供帮助和指导。AllJoyn代码库位于(http://www.allseenalliance.org)。
AllJoyn框架提供了一个抽象层以允许AllJoyn框架代码和应用运行在多个操作系统平台上。截至记者发稿时,AllJoyn框架支持大部分标准的Linux发行版,包括Ubuntu,并且可以运行在Android2.3(Gingerbread),以及之后Android版本的智能手机和平板电脑上。已测试和验证过的可以运行AllJoyn框架代码的Microsoft Windows常用版本,包括Windows XP,Windows 7,Windows RT和Windows8。另外,AllJoyn框架代码在可以运行在苹果操作系统iOS和OS X上,嵌入式操作系统如的OpenWRT,也可以工作在Unity游戏开发生态系统。
目前开发人员可以使用 C++,Java, C#, JavaScript, 和 Objective-C来编写AllJoyn应用.
现在有很多网络技术可供设备通讯使用。由于AllJoyn框架提供了一个网络抽象层,它定义了清晰的底层网络协议栈界面,使得软件工程师添加新的网络实现时非常容易。
例如,截至记者发稿时,Wi-Fi联盟近日发布Wi-Fi直连(Wi-Fi Direct)标准,它支持点对点的Wi-Fi连接。现在支持Wi-Fi Direct的一种网络模块正在被开发,对AllJoyn开发人员来说,这将透明地增加Wi-Fi直连,以及它的预关联发现机制为一个可用的网络选项。
通常,作为移动设备在它的生命周期中会不停变动位置,它和网络的关联是来来去去。这意味着,IP地址可能会改变,网络接口可能会变得无法使用,服务也可能是暂时的。
当老的服务消失时,或者新服务出现时,AllJoyn框架都会进行通知,并在必要时形成新的关联。在AllJoyn框架已准备作为Wi-Fi热点2.0(Wi-Fi hotspot)的应用层。Wi-Fi热点2.0的目的是让手机在信号发射塔和Wi-Fi热点之间的漫游透明。
如果设备需要沟通时,必须有某种形式的服务发布和发现。在过去静态网络时代,由网络管理员作出安排来使设备可以进行通信。现在零配置网络的概念已经普及,例如苹果的Bonjour和微软通用即插即用。现在有很多发现机制可用,例如蓝牙服务发现协议,以及Wi-Fi直连P2P发现规范等新兴机制。在AllJoyn框架提供了简化了定位和消费服务的过程中服务广告和发现的抽象。
注:Bonjour是苹果为基于组播域名服务(multicast DNS)的开放性零设置网络标准所起的名字。使用Bonjour的设备在网络中自动传播它们自己的服务信息并聆听其它设备的服务信息,设备之间就象在打招呼,这也是命名为Bonjour(法语:你好)的原因。这样,Bonjour使局域网中的系统和服务即使在没有网络管理员的情况下也很容易被找到。Bonjour显示局部网内支持组播域名协议的设备和应用的名称,采用multicast DNS来解决区域网内设备命名冲突。
分布式应用安全性的自然模型是应用到应用。不幸的是,在许多情况下,网络的安全性模型与此不符。例如,蓝牙协议要求设备间的配对。使用这种方法,一旦设备配对,两个设备上的所有应用被授权。不过如果考虑比蓝牙耳机功能更丰富的设备,这可能就不是预期的。例如,如果两个笔记本电脑通过蓝牙连接,更细的粒度是必要的。AllJoyn框架被设计来为复杂的安全模型提供广泛的支持,重点强调应用到应用的通信。
AllJoyn架构利用一个易于理解的对象模型和远程方法调用(RMI:Remote Method Invocation)机制。AllJoyn模式重新实现了由D-Bus规范传输的有线协议(wire protocol),扩展D-Bus有线协议来支持分布式设备。
随着标准对象模型和有线协议而来的是:规范化各种接口到组件的能力。Java接口声明提供了一个与本地实例交互的规范,以大致相同的方式,AllJoyn对象模型提供一个独立于语言的规范与远程实现进行交互。
使用规范,许多接口实现可以被考虑,从而能够实现应用程序通信的标准定义。软件组件是有利的技术。软件组件是许多现代系统的核心,在类如Android这样的系统中尤其明显,它定义了四个主要的组件类型来参与到Android应用程序框架;或者在微软系统中它使用组件对象模型(COM)系统的继任者。
我们预计,丰富的接口定义“海洋”将会出现。AllJoyn项目希望与用户合作,以定义和发布标准接口,并支持实现共享。
AllJoyn框架包含了一些抽象概念,用于帮助了解和叙述各个部分。不过对于理解基于AllJoyn系统来说,只有少量关键抽象是大家必须知道的。
本节介绍AllJoyn框架的概况,为后续更深入的文档(如详细API)提供基础。
分布式系统是为达成一个共同的目标,一组独立的计算机通过某种形式的网络相互连接进行通讯。考虑一下:运行在某台电脑地址空间上的一个程序,就像调用本地方法一样,调用位于另一个物理上独立的电脑空间上的方法或者过程。这通常是通过远程过程调用(RPC:Remote Procedure Call),或者面向对象的概念中的RMI或远程调用(RI:Remote Invocation)来完成。
RPC交换的基本模型包括一个客户端,它是RPC的呼叫者,和一个服务器(在AllJoyn模型中称为服务),其中服务器实际执行所需的远程过程。调用者执行一个客户端存根(client stub),看起来就像是本地系统上的本地过程。客户存根将过程的参数(称为编组或序列参数)打包成某种形式的消息,然后调用RPC系统来安排通过某种标准的传输机制(例如TCP)发送消息。在远程机器上,有相应的RPC系统的运行,它负责解编(反序列化)参数,并和传递消息到服务器存根,由服务器存根安排执行所需的过程。如果被调用的过程需要返回任何信息,使用类似的过程来发送返回值给客户机存根,再把它返回给原来的调用者。
注意:不要求一个过程中只执行一个独立客户端或一个独立的服务。如果两个或多个过程执行相同的客户端和服务,他们被认为是同等。在多数情况下,AllJoyn应用将执行类似的功能,他们被认为是同等。AllJoyn框架同时支持传统的客户端和服务功能,也支持点对点网络。
AllJoyn系统最基础的抽象概念是AllJoyn总线(AllJoyn bus)。它提供了一种快速,轻量级的方法在分布式系统中移动封装消息。我们把AllJoyn总线看做一种消息在其中流动的“高速公路”。下图显示单个设备上的一个AllJoyn总线实例的可能形式。
Figure: Prototypical AllJoyn bus
典型的AllJoyn总线详述如下。
· 总线本身显示为粗横黑线。垂直线可被认为是“出口”,以及消息所流过总线的源和/或目的地。
· 连接到总线被描绘为六边形。正如高速公路的出口通常被分配给数字,每个连接也被分配一个唯一的连接名称。为了清晰起见,我们这里使用简单的连接名称。
· 在许多情况下,连接到总线可以被认为是过程共驻内存。因此,唯一的连接名称:1.1
可能被分配给某个应用实例进程中的连接,:1.4
可能分配给另一个应用实例进程中的连接。AllJoyn总线的目标是运行两个应用不用关心底层细节就可以进行通信。连接的一方可以被认为是客户机存根,而另一侧可以提供服务存根的职责。
典型的AllJoyn总线图显示了AllJoyn总线的一个实例,说明了一个软件总线如何为连接到总线上的组件提供进程间通信。下图是展示了AllJoyn总线可以扩展到跨设备。当需要时,可以在智能手机上的AllJoyn逻辑总线的分段和Linux主机上AllJoyn组件之间,创建通信链路。
Figure: Device-to-device communication handled by the AllJoyn framework
这种通信链路的管理由AllJoyn系统处理,并且可以使用一些底层的技术,如Wi-Fi或Wi-Fi直连。AllJoyn总线可能涉及到多个设备,但这些对于分布式总线的用户来说是透明的。对于总线上的部件来说,分布式AllJoyn系统看起来就像是本地设备上的总线一样,它不用关注底层细节。
下图显示了分布式总线如何展示给总线的用户。一个组件(例如,智能手机连接标记:1.1
),可以发起一个过程调用到Linux主机上的标记组件 :1.7
,而无需担心和关注组件所在的位置。
Figure: A distributed AllJoyn bus appears as a local bus
设备到设备的通信演示图展示了逻辑分布式总线是由位于不同设备上的若干分段组成。实现这些逻辑总线段的AllJoyn功能被称为一个AllJoyn路由器。
术语守护进程通常用于Unix的衍生系统来描述哪些运行在系统中,提供一些系统所需功能的程序。在Linux系统上,替代守护进程的说法,我们把它称做独立的路由器。在Windows系统中,我们把它称为服务(service),不过我们指代的是AllJoyn路由器。
Figure: Relating bubble diagrams to the bus
为了更好地形象化描述AllJoyn路由器,这里我们使用气泡图。如前面的图,考虑两个AllJoyn总线分段,一个位于智能手机,一个位于Linux主机上。到总线的连接标记为客户端(C:Client)和服务(S: Service)(使用RMI模型中的概念客户端和服务)。实现分布式总线的核心的AllJoyn路由器标记为(D)。上图的部件通常被翻译为如下图所示。
Figure: AllJoyn bubble diagrams
气泡可被看作是运行在分布式系统上的计算机进程。左侧,两个客户端(C)和一个服务(S)进程运行在智能手机上。这三个进程与智能手机的AllJoyn路由器(实现了分布式AllJoyn总线的本地分段)进行通信。在右侧,有实现了AllJoyn总线Linux主机上的本地分段的路由器。
这两个路由节点协调横跨逻辑总线的消息流,把图中的分布式AllJoyn总线看做一个的完整的连接实体。类似智能手机上组成结构,在Linux主机上有两个服务组件和和一个客户端组件。
在这个例子中,客户端C1可以发起远程方法调用到远端的服务S1,就好像S1是一个本地对象一样。智能手机上的AllJoyn路由器将封装后的参数路由出本地总线分段。封装的参数通过网络链路(从客户端的角度看是透明的)发送到Linux主机上的AllJoyn路由节点。 Linux主机上的AllJoyn路由器判断数据包的目的地是S1,对参数进行解封装和排列具有解组的参数,然后调用服务的远程方法。如果有返回值,采用类似的方法反过来讲返回值返回给客户端C1。
由于独立路由器运行在后台进程,并且客户端和服务分别运行在各自独立的进程中,在每个独立的进程中,必须有一个路由器的“代表”。在AllJoyn框架把它们称为调用总线连接(bus attachments)。
每个由AllJoyn组件促成的到AllJoyn总线上的连接被称为总线连接(bus attachments)。总线连接生活在每个需要连接到AllJoyn软件总线的进程中。
讨论软件组件时,通常会在硬件和软件之间进行类比。我们可以把分布式AllJoyn总线的本地分段类比成台式计算机的硬件背板总线。硬件总线本身传输电子讯息,并有称为连接器的接入点供插入板卡。在AllJoyn框架中,连接器类似的功能是总线连接(bus attachment)。
一个AllJoyn总线连接是一个针对特定编程语言的对象,它表示分布式AllJoyn总线到客户端,服务,或同类。例如,对于c++,有一个总线连接功能的实现提供给用户,而针对Java又有另外一个执行相同的总线连接的功能提供给用户。随着AllJoyn框架对更多语言的支持,会有越来越多的变成语言实现可用。
AllJoyn框架基本上是一个面向对象的系统。在面向对象的系统中,我们讲调用对象的方法(当谈到分布式系统时使用术语远程方法调用)。在面向对象的程序设计理念中,对象有成员。经典地,还有对象方法或对象属性,在AllJoyn框架它们被称为BusMethods和BusProperties。另外AllJoyn框架还具有BusSignal,它是在一个某些事件或状态改变的异步通知。
为了透明地安排客户端,服务,和同类伙伴之间的交流,必须约定总线方法和总线信号的参数顺序,以及总线性能类型信息的格式。在计算机科学中,把对方法或信号的输入/输出类型的定义和描述称为类型识别标志(type signature)。
类型识别标志(type signature)是由字符串定义。类型识别标志可以描述字符串,所有基本类型在大多数编程语言中都可用,并且使用这些基本类型组成如数组和结构等复合类型。分配和使用类型识别标志已超出本介绍的范围,但这里会介绍: 总线方法,信号,或属性的类型签名传送到底层AllJoyn系统;如何在传递的参数/返回值和总线上传递的封装数据间转换。
在大多数的面向对象编程系统中,方法或属性集合被组合成具有一些固有的共同关系组。把这组函数的统一声明称为接口。接口是实现这个接口的实体和外部世界之间的契约。这些接口由某些标准组织来负责标准化,我们可以在各种网站上,找到大量这种规范服务,从电话到媒体播放器的控制等等。这种方式指定的接口在D-Bus规范以XML方式来描述。
接口定义收集一组总线方法,总线信号和总线属性,以及与它们相关的类型签名到一个命名空间中。在实践中,接口是由客户端,服务或同类伙伴的进程来实现。如果实现了一个命名接口,就在实现和外部世界中建立了一个隐性契约:该直接支持它所定义的所有总线方法,总线信号,以及总线属性。
接口名称通常采取反向域名的形式,例如AllJoyn框架实现的一些标准接口。AllJoyn标准接口org.alljoyn.Bus
由路由器来实施,它提供一些用于总线连接的基本功能。
值得注意的是,接口名称是一个简单的字符串,命名规则相对比较自由。但是接口名称字符串不应该与其他类似的字符串混淆,尤其是总线名称。例如,org.alljoyn.sample.chat
可能是一个总线名称,它应该是一个恒定不变的名称,以便客户端可以搜索到它。org.alljoyn.sample.chat
也可能是一个接口名称,定义与某个总线名称的总线连接相关联的总线对象可用的方法,信号和属性。总线名称的存在意味着具有给定接口名称的接口也存在;然而,它们是两个完全不同的东西,虽然有时看起来完全一样。
总线接口提供一种标准方法来声明在整个分布式系统的工作接口。总线对象提供了接口规范实现可以放置的地方,总线对象位于总线连接(bus attachment)中,并作为通信端点。
因为某个总线连接的接口可能会有多个实现,必须有附加的结构来区分这些接口实现。AllJoyn通过对象路径来解决这个问题。
正如接口名称是位于某个接口命名空间的字符串,对象路径也处在一个命名空间中。命名空间的结构为一棵树,路径是一个文件系统的目录树。就像在Unix文件系统一样,对象路径的路径分隔符是斜杠(/)。由于总线对象是总线接口的具体实现,对象路径可以遵循相应接口的命名约定。如下面的例子所示:一个接口定义了磁盘控制器接口(例如,org.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)不会随着时间而改变,我们也可以通过众所周知的总线名称来表示一个AllJoyn总线上的功能单元。正如接口名称看起来是颠倒的域名,总线名具有相同的外观。为了方便起见接口名称和公知的总线名称通常选择相同的字符串,所以这里很容易让大家产生混淆。请记住,他们服务于不同的目的:接口名称识别客户端和服务(由生活在总线连接中的总线对象来实现)之间的契约;而公知的总线名称则以一致的方式来标识客户端期望连接的服务。
要使用公知名称,应用程序(通过总线连接的方式)必须使用该名称发出一个请求到总线路由器。如果公知名称没有被其他应用程序使用,独占使用该公知名称是理所当然的,这样可以保证公知名称代表总线上唯一的地址。
通常情况下,一个公知的名称暗示了一些约定:关联的总线连接实现了一个总线对象集合,和可供可用的服务。由于总线名称提供分布式总线上的唯一的地址,它们必须在整个总线中是独一无二的。例如,人们可以使用总线名称org.alljoyn.sample.chat
,这将表明相同名称的总线连接将被实施一个聊天服务。凭借它已采取这个名字这一事实,人们可以推断它已经实现了相应的org.alljoyn.sample.chat
接口,该接口位于对象树/org/alljoyn/sample/chat
的总线对象中。
这样做的问题是,为了“聊天”,人们将期望AllJoyn总线上的存在其他类似组件也支持聊天服务。由于总线名称必须唯一标识一个总线连接,因此要求附加某种形式的后缀来确保它的唯一性。这个后缀可以是用户名,也可以是一个唯一的数字。在聊天的例子中,我们可以假设多种总线连接:
org.alljoyn.sample.chat.bob
org.alljoyn.sample.chat.carol
上面的例子中,公知名称前缀org.alljoyn.sample.chat.
充当服务名,从中可以推断出聊天接口和对象实现的存在。后缀 bob
和carol
使得公知名称的实例是唯一的。
这里有一个问题:如何在分布式系统中确认服务的位置。答案是通过服务发布和客户端执行的发现操作。
服务广告和发现有两个方面的问题。如上所述,即使服务驻留在AllJoyn总线的局部分段中,人们需要能够看到和检查所有总线上的总线连接的众“公知名称”,以确定它们中是否有自己感兴趣的服务。还有一个更有趣的问题:如何发现不属于现有总线分段的服务。
考虑一个问题:把一个运行AllJoyn框架的设备带到到另一个设备附近会发生什么。由于两个装置物理上是分离的,所以两个设备上的总线路由器无法知道彼此。路由节点如何确定对方的存在?以及它们如何确定一个需要连接上另外一个? 如何形成一个逻辑分布式AllJoyn总线?
答案是通过AllJoyn服务公告和发现服务。当在本地设备上启动了服务,它保留给定的众所周知名称,然后向周围的设备公告它的存在。AllJoyn框架提供了一个抽象层,可以让服务发送的广告透明地传过底层技术,如Wi-Fi无线,Wi-Fi直连,或其它未来的无线传输通信技术。客户端和服务都不需要关心公告是如何通过底层技术管理的。
例如,在一个联系人交换应用中,该应用的一个实例可以使用公知名称org.alljoyn.sample.contacts.bob
,并广告这个名称。这可能会引起一个或多个以下事件:一个通过连接Wi-Fi接入点的UDP多播,Wi-Fi直连(Wi-Fi Direct)中的一个预关联服务公告,或蓝牙服务发现协议的消息。发送公告者不需要关心公告如何传输。由于联系人交换应用在概念上是点对点的网络应用,因此人们期望第二个电话也会公布类似的服务,例如,org.alljoyn.sample.contacts.carol
。
Client applications may declare their interest in receivingadvertisements by initiating a discovery operation. For example, it may ask todiscover instances of the contacts service as specified by the prefixorg.alljoyn.sample.contacts
. In this case, both devices would make that request. 客户端应用程序可以通过启动发现操作来声明其想接收的公告。例如,它可能请求发现以org.alljoyn.sample.contacts
为前缀的联系人服务实例。在这个例子中,两个设备可能都将作出这样的请求。
只要电话进入附近,底层的AllJoyn系统就会通过可用的传输方式发送和接收公告。每个将自动接收相应的服务可用的指示。
由于服务公告可以通过多种传输方式接收,而且在某些情况下,它需要额外的底层工作来提供一个基本的通信机制,对于使用发现服务来说还有另外一个概念性部分,这就是通信会话。
前面已经对总线名称,对象路径,和接口名称的概念进行了阐述。回想一下,当一个实体连接到AllJoyn总线,它被分配一个唯一的名称。总线连接可以要求他们被授予一个公知名称(well-known name.)。客户端使用公知名称来定位或发现总线上的服务。例如,一个服务可以连接到AllJoyn总线和被分配的唯一名称:1.1
。如果服务想让要总线上的其他实体能够找到它,该服务必须从总线请求一个公知名称,例如,com.companyA.ProductA
(记住,通常会追加唯一的实例修饰符)。
这个名字暗示:至少有一个已实现了一些公知的接口的总线对象可用。一般在连接实例中,总线是通过使用相同的组件作为公知名称的路径来识别(这不是必须的,只是约定俗成)。在这个例子中,对应于总线名称com.companyA.ProductA
的到总线对象的路径可能是/com/companyA/ProductA
。
为了更好地理解从客户端总线连接到一个类似的服务连接的通信会话是如果建立的,并提供一个端到端的实例,我们有必要把AllJoyn机制和更熟悉的机制做个对比。
在AllJoyn框架中,服务要求一个人类可读的名称,以便它可以使用公知和容易理解的标签来公告自己。众所周知的名字必须转化为唯一的名称(底层网络正确的路由信息),例如:
Well-known-name:org.alljoyn.sample.chat
Unique name::1.1
这告诉我们,公告的公知名称org.alljoyn.sample.chat
对应于已分配的唯一名称为:1.1
的总线连接。这和企业有名字和邮寄地址类似。继续上面的类比,当一个企业与其他企业一起坐落在一个建筑内时,人们可能会发现需要进一步通过房间号来限定公司地址。因为AllJoyn总线连接(bus attachments)能够提供一个以上的服务,还必须有一种方法来识别一个连接上的多个目的地。 A“联系端口号”(contact port number)对应于邮寄地址比喻中的房间号目的地。
正如人们可以通过国家邮件系统(美国邮政总局,法国邮政瑞士)或私营公司(联邦快递,联合包裹服务公司),并使用不同的紧急程度(过夜,两天,陆路配送)寄信,当使用AllJoyn框架联系服务时,我们必须指定网络连接的某些所需特性,以提供一个完整的递送规范(例如,可靠地传递信息,可靠地传递非结构化数据,或者不可靠递送非结构化数据)。
注意上面的例子中,地址信息和配送信息的分离。正如人们可以考虑选择多种方式来从一个地方到另一个地方来获得一封信件,人们也可以选择使用不同的方式来使用AllJoyn系统递送获得数据。
正如正确标记邮信需要“邮寄地址”和“接收地址”一样,AllJoyn会话也要求“从”和“到”信息。AllJoyn系统中,在“邮件发送地址”对应于客户端组件的位置,“邮件目的地址”对应于服务。
从技术上讲,这些从或到的地址在计算机网络中被称为半关联(half-associations)。在AllJoyn框架,到服务的地址具有下面的形式:
{session options, bus name, session port}
第一个域“会话选项”(session options)涉及如何将数据从连接的另一个移动到另一侧。在IP网络中,选择可能是TCP或UDP。在AllJoyn框架,这些细节被抽象,所以选项可能是:“基于消息的”("message-based"),“非结构化数据”(unstructured data),或“不可靠非结构化数据”(unreliable unstructured dat)。服务目的地由请求的总线连接的公知名称来指定。
类似于邮政例子中的门牌号,AllJoyn模型中也存在投递到总线连接内部某个点的概念。在AllJoyn框架,我们称之为会话端口。就像房间号在一栋建筑内是唯一的,会话端口在给定总线连接范围内也是唯一的。从总线名称可以推断出联系端口的存在以及它的值;同样的方法可以推断出底层的对象和接口集合。
上面提到的“从地址”对应于客户端的信息,客户端必须有自己的半关联,以便与服务进行通信。
{session options, unique name, session ID}
不要求客户申请一个众所周知的总线名称,所以他们提供了他们的独特名称(如:1.1
)。因为客户端不会充当会话的目的地,所以它们不需要提供会话端口,但被在连接建立时候,他们会被分配一个会话ID。在会话建立过程中,会话ID返回给服务。对于那些熟悉TCP网络的人们来说,这相当于使用TCP建立连接,其中通过知名端口连接某个服务。当连接建立后,客户端使用临时端口来描述一个类似的半关联。
在会话建立过程中,两个半关联有效地结合:
{session options, bus name, session port} Service
{session options, unique name, session ID} Client
请注意这里有会话选项的两个实例。当通信建立开始,服务提供它支持的会话选项和客户端提供它所需的会话选项。会话建立过程,包括谈判决定最终在会话中实际使用的选项。一旦会话已经形成,客户端和服务侧的半关联一起确定一个唯一的AllJoyn通信路径:
{session options, bus name, unique name, session ID}
在会话建立过程中,通信路由节点之间的逻辑网络连接形成。这可能会导致产生一个无线电拓扑管理操作。如果这样的连接已经存在,就重用它。新创建的底层的路由器到路由器的连接,用于执行初始的安全检查,一旦完成,两个路由器将两个独立的AllJoyn软件总线分段加入到更大的虚拟总线中。
因为在某些通信技术中,必须使用拓扑事项来平衡底层连接的端至端流控问题,两个通信端点之间(和“从”客户机“,以”服务)的实际连接可能会,也可能不会导致一个单独通信信道形成。在某些情况下,信息流动最好是通过一个临时对等网络(ad hoc)拓扑,在某些情况下,可能最好通过一个新的TCP/ IP连接。这是另一个可能需要对底层技术的深刻理解来解决的情况,幸运的是AllJoyn框架已经为你完成了它。用户只需要知道消息被正确地路由,通过满足应用抽象需要的传输机制。
截止到AllJoyn的R14.06发行版本,应用申请加入他们自己主持的会话是不可能的。对于哪些它们自己消费自己提供的信息或服务的应用来说,这导致一个不对称:他们必须把他们自己托管的总线对象,区别于那些由其他同行托管的总线对象。自加入(self-join)功能通过允许应用程序加入自己主持的会议来消除这种不对称。因此,本地承载总线对象与远程托管总线对象可以以完全相同的方式进行处理。
有时,一个应用程序需要知道在通信信道(“导线”)中那些对等体存在,那些不存在。出于这个原因,14.06版本引入了一个PING API。PING API允许确定对端是否存在。然而对于使用PING API的应用来说,它需要定期ping对端。从14.12版本开始,AllJoyn引入了自动PING或Auto-Pinger。Auto-Pinger进行定期的对端检测,所以应用程序不再需要做这个工作。
AllJoyn框架的目的是提供一个软件总线,该总线用于管理公告和发现服务的实现,它提供了一个安全的环境,并实现位置透明的远程方法调用。传统的客户端/服务已支持,和点对点通信。
AllJoyn框架最基本的抽象概念是将所有东西捆绑在一起的软件总线。虚拟分布式总线是由每个设备上的后台程序AllJoyn路由节点来实现的。客户端和服务(和同类伙伴)通过总线连接(bus attachment)连接到总线。总线连接(bus attachment)驻留在在客户端和服务的本地进程中,并提供和本地AllJoyn路由器通话所需要的进程间通信。
当总线连接上后,系统给每个总线连接分配一个唯一的名字。总线连接可以要求一个唯一的人类可读的总线名称,并使用它通告自己给AllJoyn世界。这个知名的总线名称看起来像一个颠倒的域名,它位于一个命名空间,并且鼓励自管理命名空间。某个名称总线连接的存在意味着至少一个总线对象存在,它实现了由名称指定的至少一个接口。接口名称分配类似,但和总线名称具有不同的含义。每个总线对象生活在以总线连接为树根的树形结构中,由总线路径来描述,它并看起来像Unix文件系统路径。
The following figure shows ahypothetical arrangement of how all of these pieces are related.
Figure: Overview of a hypothetical AllJoyn bus instance
图中央的黑实线代表AllJoyn总线。该总线具有“出口”,它们是总线连接(Bus Attachments),分配的唯一名称为:1.1
和:1.4
。在图中,唯一名称为:1.1
的总线连要求称为rg.alljoyn.samples.chat.a
,并且已经被分配相应的公知总线名称。"a"被追加到总线名称上,以确保总线名称的唯一性。
取该总线名称暗示许多事实。首先,这里有一个总线对象的树形结构,它位于不同的路径。在该假设的例子中,有两个总线对象。一个是在路径/org/alljoyn/samples/chat/chat
,它大概实现了一个适合聊天的接口。另外一个总线对象在路径/org/alljoyn/samples/chat/contacts
,它实现名字为 org.alljoyn.samples.chat.contacts
的接口。因为给定的总线对象实现了接口,它必须提供相应的总线方法,总线信号,以及总线属性的实现。
数字42表示联系会话端口,客户端必须使用它来发起和服务之间的通信会话。注意,会话端口只在某个总线连接的范围内是独一无二的,所以在图中的其它总线连接中也可以使用42作为它的联系会话端口,如图所示。
请求和授予众所周知总线名称后,服务通常会广告这个名字,以允许客户端发现其服务。下图显示服务发出一个广告请求给其本地路由器。路由器根据服务的输入,判断采用何种网络媒体机制去广告服务,确定后就开始广告它。
Figure: Service performs an Advertise
当一个潜在客户希望找到一种服务来消费,它会发出一个查找名称请求。它的本地路由器设备也根据客户端的输入,决定去找广告和探针广告的最佳方式。
Figure: Client requests to Find Name
一旦这些设备接近到一定范围,他们开始可以听到对方的广告,在任何媒体启用了发现请求。下图显示托管服务的路由器听到搜索请求,并作出响应。
Figure: Router reports Found Name
最后,下面的图显示客户端接收到一个指示:在本区域内有一个新的路由器,它承载有期望的服务。
Figure: Client discovers service
开发视图中的客户端和服务都使用自己总线连接对象的方法和回调做出编排广播和发现过程的要求。服务方实现总线对象提供其服务,而客户端将期望使用代理对象来提供易于使用的界面,以方便与服务进行通信。该代理对象将使用AllJoyn ProxyBusObject来精心安排和服务的通信,并提供方法参数和返回值的编码和解码操作。
在远程方法可被调用前,必须先建立一个通信会话,以有效地将各总线分段加入到单独的逻辑总线上。广告和发现不同于会话建立。一个设备可以接收广告,但不采取任何行动。在接收到广告时,客户端才决定是否采取行动加入到通信会话中,这时总线逻辑上结合成一个整体。要做到这一点,服务必须建立一个通信会话端点并通告其存在;同时客户端必须接收该广告,并要求加入该会话。服务在公布其服务之前必须定义一个半关联(half-association)。这可能看起来如下所示:
{reliable IP messages, org.alljoyn.samples.chat.a,
42}
这表明它会通过一个可靠的基于消息的传输跟客户端通话,已采取了上面所指的公知总线名称,并预期在会话端口42进行联络。这就是出现在假想总线实例图中的情况。
假设有一个唯一名称为:2.1
的总线连接想从一个物理上的远程路由节点来连接。它将提供它的半关联到系统,一个新的会话ID将被分配,并将会话ID传送给通话双方:
{reliable IP messages, org.alljoyn.samples.chat.a, :
2.1,
1025}
新的会话将使用可靠的消息传递协议来实现(使用IP协议栈),会话存在于名字为org.alljoyn.samples.chat.a
的总线连接(服务端)和名称为:2.1的总线连接(客户单)之间。用于描述会话的会话ID由系统分配,在这个例子中会话ID是1025。
作为建立终端对端通信会话的结果,AllJoyn系统会采取任何行动来创建分布式总线图中所示的虚拟软件总线。请注意,这是一个虚拟的画面,实际上可能发生的情况是:一个基于Wi-Fi直连的点对点连接建立来承载TCP连接;或使用无线接入点来承载UDP连接,这取决于所提供的会话选项。要完成这些,无论对于客户端还是服务可能都是非常困难的工作。
此时,如果需要认证,可以开始尝试。然后客户端和服务开始使用RMI模型进行通信。
当然,该方案不限于一个客户端在一个设备上和一个服务在另一设备上。可以有任意数量的客户端和任意数量的服务(受限于设备或网络容量)组合以实现某种形式的协同工作。总线连接可以同时承担客户端和服务,并实施点对点服务。 AllJoyn路由器承担将许多分离的组件整合成一个可管理的逻辑单元,并路由消息。此外,接口描述和语言绑定的性质允许用不同的编程语言的组件之间的互操作性。
从AllJoyn系统的用户的角度来看,要理解的体系结构的最重要部分是,客户端,服务或对端(peer)。从系统的角度来看,三个基本用例之间真的没有什么差异;只是同样的系统功能的不同使用模式而已。
下图显示了从用户(不是AllJoyn路由器)的角度来看的系统体系结构。
Figure: Basic client, service, or peer architecture
在最上层的是语言绑定(language binding)。AllJoyn系统用C++语言编写,所以对于这种语言的使用者来说,不要求绑定。然而,对于其他的语言,例如Java或JavaScript的用户来说,这里提供一个相对薄的翻译层称为语言绑定(language binding)。在某些情况下,绑定可扩展到提供系统特定支持。例如,一个通用的Java绑定可以让在AllJoyn系统在Java系统中使用,而Jave可以运行在Windows或Linux上;Android系统绑定可以将AllJoyn系统整合进Android系统,例如作为一个Android应用框架服务组件。
系统和语言绑定是建立辅助对象之上的,辅助对象设计用来让AllJoyn系统中常见的操作更容易。也可以使用许多AllJoyn系统而不使用这些助手;不过还是鼓励使用它们,因为它提供了抽象接口的另一个层次。前面章节中提到的总线连接是一个重要的帮手,如果没有它,系统是不可用的。除了所提供的一些关键功能,总线连接还提供了一些方便的功能,使管理和与底层软件总线互动更容易。
辅助层之下是消息传递和路由层。把参数和返回值解包和封包到消息(通过总线传输消息)的功能在该层完成。路由层安排递送入站消息到适当的总线对象和代理,并为发送给路由器用于递送的消息安排去往的总线连接。
消息传递和路由层和端点层(endpoint layer)进行交流。在AllJoyn系统底层,数据从一个端点移动到另一个端点。这是从网络代码的角度来看的一个抽象通信端点。在端点层的顶部,网络抽象是完整的,在那里,通过非Wi-Fi无线(蓝牙),和通过有线以太网的连接是没有任何区别的。
端点是被称为传输(transports)的传输机制的具体实体,它提供了基本的网络功能。在一个客户端,服务或对端中,所使用的唯一的网络传输是本地传输。这是到本地AllJoyn总线路由器的本地进程间通信链路。在基于Linux的系统,这是一个Unix域套接字连接;在基于Windows的系统,这是一个到本地路由器的TCP连接。
AllJoyn框架提供一个OS抽象层,以提供一个平台,在其上建立系统的剩余部分;最底层的是原生系统(native system)。
AllJoyn路由器是将AllJoyn系统结合在一起的粘合剂。如前所述,路由器是在后台运行的程序,等待有趣的事件发生,然后回应它们。因为这些事件通常是外部的,最好是从自下而上的角度来看待路由器的架构。
下图中路由器的最底层是原生系统(native system)。类似于客户端架构,我们使用操作系统抽象层为在Linux,Windows和Android上运行的路由器提供通用的抽象。操作系统抽象层之上,我们有路由器的各种低级网络组件。回想一下,客户端,服务,和对端仅使用本地进程间通信机制跟一个路由器交互,因此路由器必须处理一个给定平台上的各种可用的传输机制。注意在路由器结构图中,“本地”传输是到AllJoyn客户端,服务,和对端的唯一连接。
Figure: Basic router architecture
例如,一个蓝牙传输将处理蓝牙系统中创建和管理微微网(Piconet )的复杂性。此外,蓝牙传输提供服务广告,适当的蓝牙发现功能,以及提供可靠的通信。蓝牙等传输方式将和IP传输一起加入到传输层。(Piconet 指用蓝牙技术把小范围(10-100m)内装有蓝牙单元(即在支持蓝牙技术的各种电器设备中嵌入的蓝牙模块)的各种电器组成的微型网络,俗称微微网。)
有线,无线网络和Wi-Fi直连传输都属于IP分组,因为所有这些传输中都使用底层TCP-IP网络协议栈。关于如何服务广告和发现完成,它们存在显著的差异,因为这些功能是在TCP-IP标准的范围之外,所以有专门从事这项功能的模块。
各种特定技术的传输实现被收集到一个网络传输的抽象中。会话模块处理通信连接的建立和维护,使路由器和AllJoyn应用的集合显示为一个统一的软件总线。
路由器使用端点的概念,以提供连接到本地客户端,服务,和对端; 它还扩展使用这些对象到总线对总线连接,这是路由器用于从主机到主机发送消息的传输。
除了由这些连接隐含的路由功能,一个AllJoyn路由器提供它自己的端点对应于用于管理或控制由路由器实现的软件总线段的总线对象。例如,当一个服务请求发布公知的总线名称,实际发生的是,在该服务的助手将这一请求转换成一个远程方法调用,然后被引导到路由器上实现的总线对象。正如在服务的情况下,路由器有一些总线对象住在实现特定命名接口的关联对象路径中。控制AllJoyn总线的低层机制发送远程方法调用到这些路由器总线对象。
路由器操作的某些方面是由一配置子系统控制的。这使得系统管理员可以指定系统的某些权限,并提供按需创建服务的能力。此外,资源消耗也可由路由器的配置锁限制,例如,允许系统管理员限制在任何给定的时间内的TCP连接活跃数量。这里还有一些选项,以允许系统管理员通过限制目前认证连接的数量,来减轻拒绝服务的某些攻击的影响。
AllJoyn框架旨在提供一个框架,在异构系统与移动元素部署分布式应用的综合系统。
AllJoyn框架提供的解决方案,建立在成熟的技术和标准的安全系统上,以一种连贯的系统的方式解决在不同网络技术之间的互动。这使得应用程序开发人员能够专注于他们的应用程序内容,而不需要关注大量的低层次网络知识。
AllJoyn系统被设计成作为一个整体工作,不再受困于由不同部分组成的临时对等网络所固有的阻抗失配。我们认为,AllJoyn系统可以使开发和部署分布式应用比那些在其他平台上开发的显著简单。