说明:这篇文章是我翻译JXTA programer's guid中的,在2.5版本中也有这个内容,不过在章节编制上有出入。由于最近正学习如何在两个Peer之间如何传送消息,故没有按照章节顺序,而是先看了这篇文章,并翻译出来供大家学习。
另外,一直没搞明白文章中有图片时,为何粘贴到这里后就看不到图片了,知道的话请站内告诉我。需要看这些图片的话,就请直接下载JXTA programmer's guid.pdf文件看图片。
在两个Peer之间发送消息
在这部分,通过实例说明如何用Pips来在两个Peer之间传送消息。同时也展示了如何实例化RendezvousListener接口。这部分的例子由两个应用程序组成:
l PipeListener---从一个文件((examplepipe.adv)中读入一个管道通告(pipe advertisement),创建一个输入管道。并监听这个管道上的消息。
l PipeExample---从一个文件((examplepipe.adv)中读入一个管道通告(pipe advertisement),创建一个输出管道,并通过这个管道发送一个消息。
当这两个应用程序运行后,都会在控制台输出一些必要的信息以显示程序运行状态。PipeListener应用程序会输出这些信息:
PipeExample应用会输出这些信息:
注意:如果你是在同一台计算机上运行这两个程序,那你应该让它们两个在不同的文件夹中运行,这样可以使得它们使用不同的端口。
在看应用程序之前,下面先介绍一些有关JXTA中“管道服务”、“输入管道”和“输出管道”的背景知识。
管道服务(JXTA Pipe Service):
类PipeService定义了一组如何在一个对等组中创建和访问管道的接口。管道(Pipe)是在两个JXTA应用或服务之间传递消息的核心机制。管道为两个对等的之间通信提供了一个简单的、非直接的、异步的通道,JXTA消息就是在输入管道和输出管道直接进行交换传递。一个应用程序如果想从其它对等点那里接受消息,那么它就应该创建一个输入管道,并且将这个管道同某一个管道通告(Pipe Advertisement)绑定起来。最后,它还要发布这个通告。这样,其它想与它通信的对等点或者服务就可以创建相应的输出管道,以便发送消息。
管道在JXTA网络中有一个唯一的ID,即PipeId (UUID),以和其它管道区别开来。这个ID被封装在管道通告中。输入管道和输出管道就是通过这个PipeId 关联起来的。
在PipeListener和PipeExample应用程序用到了下面这些类:
l net.jxta.pipe.PipeService---定义了管道服务的API
l net.jxta.pipe.InputPipe---定义了从PipeService中接收消息的接口。一个应用程序要从管道中接收消息,就应该先创建输入管道。而输入管道InputPipe就是从PipeService中创建和返回的。
l net.jxta.pipe.PipeMsgListener---监听PipeMsgEvent事件的监听接口
l net.jxta.pipe.PipeMsgEvent---包含了从管道中接收的事件
l net.jxta.pipe.OutputPipe---定义了从PipeService发送消息的接口。一个应用程序要向管道中发送消息,就应该先从PipeService中获得一个OutputPipe。
l net.jxta.pipe.OutputPipeListener---OutputPipe事件的监听接口
l net.jxta.pipe.OutputPipeEvent---包含了处理输出管道时所得到的的事件
l net.jxta.endpoint.Message---定义了利用PipeService API所接收或者发送的消息的接口。一个消息包含了一组消息元素(MessageElements),每一个消息元素又包含了“名字空间”、“名称”、“数据”和“签名”等几项。
管道监听器(PipeListener) :
这部分的应用程序创建了消息,并且在输入管道上监听这个消息。它只定义了一个类PipeListener,这个类实现了PipeMsgListener接口,这两个类常量包含了将要创建的管道的相关信息:
l String FILENAME ---这是一个XML文件,包含了一些以文本形式表示的管道通告的内容(这个文件必须存在,并且必须包含一个可用的管道通告,否则程序就无法正常运行)。
l String TAG ---消息元素的名字,或者标签。我们接收任何消息都要用到这些标签。
我们同时也定义了四个变量:
l PeerGroup netPeerGroup ---默认的对等组
l PipeService pipeSvc ---这是管道服务,我们要用它来创建输入管道并且监听消息
l PipeAdvertisement pipeAdv ---管道通告,我们创建输入管道时用到它。
l InputPipe pipeIn ---我们所创建的输入管道
main()方法
这个方法创建一个PipeListener对象。调用startJxta()方法来初始化JXTA平台,创建默认的对等组。然后调用run()方法,该方法中创建一个输入管道,并将之注册为PipeMsgListener。
startJxta()方法:
初始化JXTA平台,创建默认的对等组:
netPeerGroup = PeerGroupFactory.newNetPeerGroup();
然后从默认的对等组中获取管道服务,在后面创建输入管道时要用到这个服务:
pipeSvc = netPeerGroup.getPipeService();
接着,通过读入文件examplepipe.adv来创建一个管道通告:
FileInputStream is = new FileInputStream(FILENAME);
要注意文件examplepipe.adv必须存在,并且是合法可用的XML文件,包含一个管道通告,否则程序会发生例外。当前这个程序要创建一个输入管道,想对应了另一个程序要创建一个输出管道,它们两个都要读这个文件。这个文件的内容会在后面给出。
通过调用AdvertisementFactory.newAdvertisement()方法来创建一个管道通告:
pipeAdv = (PipeAdvertisement)AdvertisementFactory.newAdvertisement
(MimeMediaType.XML_DEFAULTENCODING, is);
run()方法:
在这个方法中,通过PipeService.createInputPipe()来创建一个输入管道:
pipeIn = pipeSvc.createInputPipe(pipeAdv, this);
由于我们还要监听这个输入管道的事件,所以调用createInputPipe()方法时有两个参数:
l PipeAdvertisement adv---要创建的管道的通告
l PipeMsgListener listener---接收输入管道事件的对象
在创建这个输入管道的时候,就把程序自身注册为监听器。所以,在这个管道中任何时候有消息事件pipeMsgEvent时(例如一个消息到来时),程序就以异步方式自动调用方法pipeMsgEvent()。
pipeMsgEvent()方法:
任何时候在输入管道中有管道事件发生时,该方法就被调用,是以异步方式的。该方法只有一个参数:
l PipeMsgEvent event---发生在管道中的事件
在该方法中,首先调用PipeMsgEvent.getMessage()获取消息:
msg = event.getMessage();