javaplatform:JXTA Platform JAVA参考实现源代码分析系列文章(2)

2002 年 7 月 23 日

本文依次剖析集中式(JDK)和对等环境下(JXTA)管道实现方式对比分析其异同然后尝试在JXTA中建立个虚拟全双工管道
引言

管道概念源于Unix,是区别线程的间直接传输数据基本手段JDK中java.io包中就有管道类同时管道在JXTA中是最基本概念是对等点的间数据传输主要方式对等管道协议(PBP)明确规范标准了对等管道绑定解析响应

本文依次剖析集中式(JDK)和对等环境下(JXTA)管道实现方式对比分析其异同然后尝试在JXTA中建立个虚拟全双工管道

本文目标是通过对区别环境下管道实现方式对比分析来理解为什么JXTA采用管道作为基本数据传输手段

管道形象化描述

个生活中情景:现在有两个地区A,BA是石油生产区B是石油消费区现在B地区需要消费A地区石油当然可以通过海运空运获得然而最通常方式是架设输油管道如图所示:



java中流概念和管道概念都可以通过此案例阐述A和B的间连接就是管道负责将A石油向B输出A向管道输出数据(output)B从管道输入数据(input)可以这样理解管道是A输出对象是B数据源这里就产生了 3个类:输出流A输入流B管道输入流B负责如何获取数据(read 操作)输出流A负责如何消费数据(write操作),管道负责连接它们(connect 操作)其实在实现时管道类分解为管道口管道出口由入口出口负责连接在复杂网络环境中这种连接方式可以有专门网络协议负责(例如JXTA中PBP,全称Pipe Bind Protocol)

由以上描述我们可以清楚知道最原始管道就是单向文章后面介绍双向管道是用两个单向管道虚拟而非真实连接方式不难发现管道最关键问题是如何协调输出(A)和输入(B)这在区别网络环境会遇到区别问题最简单是同JVM下区别过程(线程或任务)的间用同步方式传递数据而对等环境下如何去发现对方就是个很现实问题这仅仅只是问题其中的下面章节会依次分析

集中式环境下管道实现

问题描述:A和B是在同JVM中A,B有方能够发现另存在A将数据发往B方A发送数据和B接收数据是相互独立

现在回到问题最初:为什么要使用管道?A只管发送B只管接受那么数据在哪儿呢?经过下面分析就会明白管道把管理数据缓冲区重任交给了他自己A,B均是围绕这个缓冲区来启停线程显然这才是问题本质

JDK中类PipeInputStream(即前面所述B)和PipeOutputStream(即前面所述A)可以很好解决这问题首先给出类图如下



下面是将类PipeOutputStreamconnect思路方法代码简化后给予注释

public synchronized void connect(PipedInputStream snk) throws IOException { sink = snk; //将PipeInputStream例子作为PipeOutputStream个属性以便 snk.in = -1;//缓冲区输入位置<0表示缓冲区为空 snk.out = 0;//缓冲区输出位置 snk.connected = true; }




连接以后PipeOutputStreamwrite操作直接sink.receive(b);这样对缓冲区buffer维护就变成了read和receive操作的间线程同步JDK对缓冲区处理非常巧妙采用了循环列表它用缓冲区标志位变化来代替数据移动类似于生活中时钟把线性时间规范标准为24小时来表示这不属于本文论述范围就不继续分析了

read操作正常情况下从out位置读取数据缓冲区空时进入等待状态以轮询方式(1秒间隔)来自我释放

receive操作正常情况下向in位置写入数据缓冲区满时进入等待状态同样以轮询方式(1秒间隔)来自我释放

JXTA对等管道实现

通过对JDK分析我们可以了解到在集中式环境下管道架设方案是比较简单在对等环境下(分布式环境下也类似)出于同样目标遇到问题却在急剧扩大例如管道入口和出口的间如何相互发现?数据如何保证在区别环境下传送?甚至对管道本身概念发生质疑:定是单入口单出口吗?

JXTA规范标准中管道是在端点的上服务或应用的间发送和接收信息虚拟连接通道管道提供在对等端点传输的上网络抽象管道有点到点和广播两种通信模式

JXTA是通过管道广告来唯标示管道输出管道要找到和其广告相同输入管道才能发送数据广告内容如下

<!DOCTYPE jxta:PipeAdvertisement> <jxta:PipeAdvertisement xmlns:jxta="http://jxta.org"> <Id> urn:jxta:uuid-59616261646162614A787461503250335003093E73074218AE3ABBE08EF3CBE303 </Id> <Type> JxtaUnicast </Type> <Name> PipeExample </Name> </jxta:PipeAdvertisement>




如果您需要对JXTA管道有例子化概念请参考Sing Li使p2p能进行交互操作:Jxta命令shell ,这篇文章有部分内容专门介绍了如何在通过shell使用管道本文主要是从编程视角去看管道是如何实现

4.1 客户视角

Project JXTA : Java Programmer's Guide Chapter7有个例子阐述如何去在对等点的间发送信息读者可以到 www.jxta.org下载源码现在从客户视角简要分析它传送原理要深入了解可以看下系统视角分析

该例中有两个对等点并且构建了两个区别类:个负责接收(Pipelistener)个负责发送(PipeExample)具体接收次序可以参考时序图:



类Pipelistener实现了接口PipeMsgListener,类PipeExample实现了接口OutputPipeListener

由时序图(这是两个JVM中所以时序符号是独立标示)可以清晰获知各个对等点前1,2步是相互独立各自第3步采用回调方式建立输入和输出管道旦对等系统探测到对方存在就分别触发各自事件发送或接收消息显然JXTA中管道是异步

调试该例程时注意先建立输入管道然后建立输出管道输出管道在时间和次数内探测不到输入管道存在就会主动放弃否则容易让网络系统在这些无休止探测中瘫痪

4.2 系统视角

从上面例程中可以了解对等管道创建思路方法以及数据流程但是不能明确对等系统是如何去实现JXTA中管道实现比在JDK中实现要复杂得多具体技术标准可以参考对等管道绑定协议(PBP),此协议规范标准了JXTA中管道概念但并没有涉及到如何去实现这同样是所有JXTA协议特征它们目标是阐述what it is,而把how to do it留给开发者这样有利于增强系统开放性其中Java参考实现就是该协议实现个案例以下将具体分析

首先看管道实现类图(以单播为例):



关键类:

InputPipeImpl :输入管道实现类
NonBlockingOutputPipe :输出管道实现类
PipeServiceImpl :管道服务实现类负责创建输入输出管道
PipeResolver :提供管道绑定解析服务

通过客户视角分析可以得知系统外部是通过PipeServiceImpl来获取输入输出管道那么消息是如何在对等系统中通过管道过滤和传递? 从实现角度涉及到太多技术细节JXTA参考实现中有着庞杂监听系统本文尝试用个案例从两个层次去解析这个问题两个层次分别是消息具体形式服务和端点协议具体分发策略很显然这里我们把注意力放在了管道架构路径上而把如何去架构放在了我想它们是有先后关系并且距离并不遥远

案例描述

现在假设有两个对等点alas 和sisal ,在个局域网内按照客户视角那例程sisal先建立输入管道alas建立输出管道由于同网内可以用广播方式发送查询信息可以不设rendevous,并且路由是两点间消息传递过程得到了简化

案例分析

以上案例中从输入输出管道建立到完成对接并传输数据总共有5个步骤:

  1. sisal建立输入管道
  2. alasl建立输出管道需要查找输入管道通过广播向网络发出管道查询消息
  3. sisal获得alas管道查询消息通过单播向sisal发出响应表示
  4. alas获得sisal响应通过单播向alas发出数据
  5. sisal获得数据 6.1 输入管道建立

    sisal通过管道服务(pipeserviceImpl)创建输入管道InputPipeImpl,并将自己注册端点服务和管道解析服务中

    6.2 输出管道建立

    alas通过管道服务,分析管道广告把自己注册于管道服务和管道解析服务然后转交管道解析服务查询是否存在本地或缓存Cache中不存在则通过集中服务向网络发送广播rendevous首先将广播消息给端点服务由端点服务决定用哪个网络协议本案例中端点服务采用TCP协议发送广播

    广播消息内容如下(消息是名称类型内容构成 3元组类型可以是xml也可以是 2进制以下列出均用xml格式所以省略了type)

    name=RendezVousPropagate content= <?xml version="1.0"?> <!DOCTYPE jxta:RendezVousPropagateMessage> <jxta:RendezVousPropagateMessage xmlns:jxta="http://jxta.org"> <TTL> 7 </TTL> <DestSName> urn:jxta:uuid-DEADBEEFDEAFBABAFEEDBABE0000000205 </DestSName> <DestSParam> jxta-NetGroupORes </DestSParam> <Path> urn:jxta:uuid-59616261646162614A78746150325033BFED264F86E14966B71A855134C813A503 </Path> <MessageId> 1023521770614 </MessageId> </jxta:RendezVousPropagateMessage> name=RendezVousPropagateurn:jxta:jxta-NetGroup content= <?xml version="1.0"?> <!DOCTYPE jxta:RendezVousPropagateMessage> <jxta:RendezVousPropagateMessage xmlns:jxta="http://jxta.org"> <TTL> 7 </TTL> <DestSName> urn:jxta:uuid-DEADBEEFDEAFBABAFEEDBABE0000000205 </DestSName> <DestSParam> jxta-NetGroupORes </DestSParam> <Path> urn:jxta:uuid-59616261646162614A78746150325033BFED264F86E14966B71A855134C813A503 </Path> <MessageId> 1023521770614 </MessageId> </jxta:RendezVousPropagateMessage> name=jxta-NetGroupORes content= <?xml version="1.0"?> <!DOCTYPE jxta:ResolverQuery> <jxta:ResolverQuery xmlns:jxta="http://jxta.org"> <HandlerName> JxtaPipeResolver </HandlerName> <Credential> </Credential> <QueryID> 0 </QueryID> <SrcPeerID> urn:jxta:uuid-59616261646162614A78746150325033BFED264F86E14966B71A855134C813A503 </SrcPeerID> <Query> <?xml version="1.0"?> <!DOCTYPE jxta:PipeResolver> <jxta:PipeResolver xmlns:jxta="http://jxta.org"> <MsgType> Query </MsgType> <PipeId> urn:jxta:uuid-59616261646162614A757874614D504725184FBC4E5D498AA0919F662E40028B04 </PipeId> <Type> JxtaUnicast </Type> </jxta:PipeResolver> </Query> </jxta:ResolverQuery>




    6.3 响应查询信息

    sisal网络端口监听到alas广播消息将消息转发给端点服务处理端点服务查询了消息内容又转发给集中服务集中服务又将查询内容转交解析服务处理然后解析服务转交给管道解析服务此时发现本地注册广告就是所要查询广告因此返回响应消息给了解析服务然后有端点服务负责发送回应消息

    响应内容:

    <?xml version="1.0"?> <!DOCTYPE jxta:PipeResolver> <jxta:PipeResolver xmlns:jxta="http://jxta.org"> <MsgType> Answer </MsgType> <PipeId> urn:jxta:uuid-59616261646162614A757874614D504725184FBC4E5D498AA0919F662E40028B04 </PipeId> <Type> JxtaUnicast </Type> <Peer> urn:jxta:uuid-59616261646162614A7874615032503386E8880590814538A64682785564B9A603 </Peer> <PeerAdv> 对等点广告内容较多所以省略了 </PeerAdv> </jxta:PipeResolver>




    6.4 接收响应消息发送数据

    alas网络端口收到sisal发送响应消息转交端点服务对路由信息处理以后转交解析服务然后到管道解析服务发现注册表中含有客户端事件(listener)则触发该事件发送数据

    6.5 获得数据

    sisal网络端口收到alas发送数据转交端点服务对路由信息处理以后发现注册表中含有客户端监听事件则触发该事件分析数据从下面消息内容可以发现所得到数据就是:Hello from peer alas

    获得消息如下

    name= jxta:EndpoSourceAddress content = tcp://192.168.0.58:9703/ name= jxta:EndpoDestinationAddress content = tcp://192.168.0.58:9701/EndpoRouter/jxta-WorldGroup name = Jxta:EndpoRouter content = <?xml version="1.0"?> <!DOCTYPE jxta:EndpoRouterMessage> <jxta:EndpoRouterMessage xmlns:jxta="http://jxta.org"> <jxta:Src> jxta://uuid-59616261646162614A78746150325033A85AC96048BF4C5A98438038268F5E7003 </jxta:Src> <jxta:Dest> jxta://uuid-59616261646162614A7874615032503386E8880590814538A64682785564B9A603/ PipeService/urn:jxta:uuid-59616261646162614A757874614D504725184FBC4E5D498AA0919F662E40028B04 </jxta:Dest> <jxta:Last> jxta://uuid-59616261646162614A78746150325033A85AC96048BF4C5A98438038268F5E7003 </jxta:Last> <jxta:NBOH> 1 </jxta:NBOH> </jxta:EndpoRouterMessage> name = PipeListenerMsg content = Hello from peer alas




    6.6 小结

    从消息传递和处理可以看出JXTA系统中各个服务的间有着清晰职责划分这样体系结构非常有利于提供给客户透明管道相对于用户而言在JXTA使用管道和在集中式环境下(Jdk)下区别仅仅在于增加了管道广告来标示管道而不需将输入管道和输出管道放在起成对使用

    从上面案例中还会发现如果用是同个管道广告可以有多个发送者个接收者这相比成对使用输入输出用途更广当然JXTA还支持多对多广播管道不过实现方式和单播不太并且正在完善中

    如何去构建个全双工对等管道

    上述例程中A是信息发送者B是信息接收者信息单向传输能否AB既是发送者又是接受者呢?解决办法很简单再建立条从B到A管道然后将这两条管道绑定在JXTA工具包net.jxta.impl.util含有BidirectionalPipeService类实现了这目标类图如下:



    类图下面 3个类和个接口均是内部类Pipe是个封装完好双向管道建立管道过程如下时序图:(这时序图视角是客户对象A,B是如何外部连接)



    以上时序图中Aaccept和Bconnect个异步操作他们互相连通以后返回Pipe类对象pipePipeinputPipe和outputPipe负责从对方获取信息和向对方发送信息它们互不干扰当然同步性也没有控制很像实际生活中IP电话

    Aaccept和Bconnect完成了A和B两次通信过程建立了两个独立管道其过程如下:(首先外部已建立了从B到A临时管道)

    1. A监听B信息
    2. B创建输入管道广告以此产生输入管道inputPipe然后按消息name=inputPipeAdv将广告发送出去
    3. A收到B消息以inputPipeAdv内容作为管道广告创建输出管道outputPipe然后创建输入管道广告以此产生输入管道inputPipe然后按消息name=inputPipeAdvAck将广告发送出去
    4. B收到A消息以inputPipeAdvAck内容作为管道广告创建输出管道outputPipe
    5. A,B均返回 Pipe(inputPipe,outputPipe) 整理总结

      漫长论述过程完成了个目标弄明对等点A和B是如何通过管道通讯对于JXTA开发人员个很重要原则就是明白自己所在协议层次维护好JXTA协议清晰层次结构对于整个系统可扩展和和可维护性均是至关重要管道在JXTA内部构建过程可以让我们感觉到JXTA协议职责在Java参考实现中有着明确划分

      在复杂对等环境中对等点的间有价值通信是非常重要而如何通信又是个很复杂问题管道服务提供了这种便捷通信抽象留给服务享受者只有 3个概念:管道广告入口出口所以我想这就是JXTA采用管道作为基本数据传输手段个很重要思想方式



      参考资料

      • 官方 Jxta 社区位于 Jxta.org您可在这里找到最新规范标准、文档、源代码和 2进制文件

      • 在 developerWorks Java 技术专区查找更多 Java 参考资料

      • Early Adopter JXTA 作者 Sing Li

      Tags:  javaplatformse6 javaplatform下载 java2platform javaplatform

      延伸阅读

最新评论

发表评论