AllJoyn基本概念的知识点
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守护进程建立了许多不同组件和消息路由的管理逻辑单元。此外,接口描述和语言绑定的性质可以允许不同编程语言编写的组件之间的互操作性。
官方网站:
https://www.alljoyn.org
https://developer.qualcomm.com/develop/mobile-technologies/peer-peer-alljoyn
更多开发信息请访问:高通开发者专区