JXTA核心协议之对等机发现协议(PDP)

 JXTA核心协议之对等机发现协议(PDP-peer discover protocol)
PDP主要用来发布自己的advertisement信息,和查找其他Peer的advertisement。Advertisement是Peer之间各
种信息交流的基本单元,发现其他Peer及其他Peer及其资源的问题就转换为发现描述各资源的Advertisement
的问题,只要找到对应的Advertisement,就相当于找到了该资源。
PDP定义了发现其他Peer和资源的协议,该协议包括两个方面,一方面用于请求获得其他Peer的Advertisement
;另一方面用于响应其他Peer的这种请求。
1.PDP的消息格式
    PDP只由两种格式构成,他们是:用于发现Advertisement的请求格式;用于响应请求的响应格式。这两种
消息,定义了两个Peer之间互相发现对方所需的所有元素。(虽然discovery消息定义了请求和对应的响应,
有很多原因会造成对应某请求的响应收不到)。
2.Discovery Query Message
    一个Peer想要寻找某种Advertisement时,就会发出Discovery Query Message(Discovery请求消息),
这个请求消息的格式如下:
<?xml version =”1.0” encoding =”UTF-8”?>
<jxta: DiscoveryQuery>                  
<PeerAdv>…</PeerAdv>                    //可选,Peer ID;如果为null,则转向所在PeerGroup。
<Type>…</Type>                                //有三种类型,PEER(0),GROUP(1),ADV(2)。
<Attr>…</Attr>                                     //可选,指明响应Advertisement中的元素名条件
<Value>…</Value>                           //可选,指明响应Advertisement中的元素值条件
<Threshold>…</Threshold>                //可选数字,指明最多可以接受Advertisement数目。          
</jxta: DiscoveryQuery >
特殊情况:
当Type设为0时,即请求获得Peer Advertisement时,将threshold也设为0,发出这种请求意味着请求方想想
获得所有的Peer Advertisement。这样收到请求的所有Peer都响应,提供自己的Peer Advertisement。
如果Attr和Value的值没有设定,其他Peer响应时回复的是Advertisement的随机集合,当然前提是符合Type指
定的类型而且未超过Threshold元素规定的最大响应数目。
3.Discovery Response Message
     为了回复Discovery Query Message,Peer创建一个Discovery Response Message,其中包含符合请求中
要求的Advertisement,如Attr/Value要求或Advertisement类型的要求。
<?xml version =”1.0” encoding =”UTF-8”?>
<jxta: DiscoveryQuery>
<Type>…</Type>
<Count>…</Count >            //包含integer值的可选元素,代表Message中响应元素的总数目。
<Attr>…</Attr>
<Value>…</Value>
<PeerAdv>…</PeerAdv>
<Response Expiration =”expiration time”>…</Response>
</jxta: DiscoveryQuery >
Response:一个可选元素,包含符合Discovery Query Message中搜索要求的Advertisement。每个Discovery
Response Message可以包含多了Response元素,没个元素只包含一个Advertisement。而Response元素个数之和为Count的值。Response元素中的Expiration属性指明Advertisement的有效时间长度,当然,这个时间以毫秒为单位。
4.Discovery Service
    服务的实例都与特定的Peer Group相关联。只有同一个Peer Group中的Peer才能通过服务来相互通信。默
认情况下,所有的Peer都属于一个大的Peer Group,称为NetPeerGroup,因而所有的Peer及其Advertisement
能相互发现。Discovery Service提供了如下功能:
获得远程的Advertisement
获得本地的Advertisement
将Advertisement发布到本地
将Advertisement发布到远程
释放本地Advertisement
DiscoveryService接口为开发人员提供了简单的方法来发送discovery请求和处理discovery响应。使用其方法
来发送Discovery Query Message甚至不需要开发人员创建和发布DiscoveryQuery对象。
5.DiscoveryListener接口
    发现discovery请求后,接到响应时应用程序需要获得通知以便取得响应中的Advertisement。在Java参考
实现中,可以给Discovery Service注册一个listener对象,当Discovery Response Messages到达时可以通过
DiscoveryService获得通知。
    每次DiscoveryService实例收到Discovery Response Message,都会调用该listener的discoveryEvent方
法,并传递事件本身,事件中包括了响应的细节。但discoveryEvent的方法必须用到DiscoveryEvent类的参数

6.DiscoveryEvent类
    作为discoveryEvent方法的参数,是为了提供DiscoveryService实例收到的Discovery Response Message
的详情。
7.发现远程的Advertisements
    DiscoveryService接口提供了简便的方法来给其他Peer发送Discovery Query Message,不需要自己创建
DiscoveryQueryMsg实例,而是用getRemoteAdvertisements方法。它有五个参数,第一个参数为Peerid,如果
为空,则会把请求发给本地的网络上的所有Peer,并通过Rendezvous Peer对外广播。(参考下程序Line38~39

8.发现缓存中的Advertisement
   响应一个Discovery Query Message的Advertisement会自动保存在本地的Advertisement缓存中DiscoveryListener,实现中不需要再写缓存的函数。并通过DiscoveryService接口的getLocalAdvertisements方法。这与寻找远程的Peer不同,用此方法可以马上得到结果,不需要用DiscoveryListener实现来处理在DiscoveryResponseMsg响应中返回的Advertisement,马上返回一个与请求参数相匹配的Advertisement的Enumeration。
9.清除缓存中的Advertisement
   有时,应用程序可能想清除所有的缓存,比如应用程序很久没有使用,估计所有Advertisement都已失效。
通过下面的方法来清除缓存中的Advertisement:    public void flushAdvertisement (String id,int type);
10.关于Advertisement的一些问题
    使用Advertisement:所有的Advertisement都是从net.jxta.document.Advertisement抽象类继承而来的。Advertisement定义了几个方法,最重要的是getDocument方法。该方法将Advertisement转换为特定MIME类
型的Document实例。
    实例化一个Advertisement:
PeerAdvertisement peerAdv = (PeerAdvertisement)   AdvertisementFactory.newAdvertisement(“jxta:PA”);
 或将“jxta:PA”改为:
       PeerAdvertisement.getAdvertisementType()。
发布Advertisement:发布有本地发布和远程发布。
本地发布方法有:
public void publish (Advertisement adv, int type)throws IOException;
public void publish (Advertisement adv,int type,long lifetime,long lifetimeforOhers)throws IOException;
远程发布方法有:
public void remotePublish (Advertisement adv, int type);
public void remotePublish (Advertisement adv, int type, long lifetime);
11.应用实例
//Source Code: DiscoveryDemo.java
 
1   import java.util.Enumeration;
2   import net.jxta.discovery.*;
3   import net.jxta.exception.*;
4   import net.jxta.peergroup.*;
5   import net.jxta.protocol.*;
6  
7   public class DiscoveryDemo implements Runnable, DiscoveryListener {
8  
9      static PeerGroup netPeerGroup = null;
10      private DiscoveryService discovery;
11
12      // 开始配置JXTA平台
13      private void startJxta() {
14          try {
15              netPeerGroup = PeerGroupFactory.newNetPeerGroup();
16          }catch ( PeerGroupException e) {
17
18              //如果不能实例化Peer Group,输出原因并结束程序。
19              System.out.println("Fatal error : group creation failure");
20              e.printStackTrace();
21              System.exit(1);
22          }
23
24      //从Peer Group中发现的服务器
25      discovery = netPeerGroup.getDiscoveryService();
26      }
27
28      // 线程将每分钟循环一次,直到发现Peers为止,并显示找到的结果
29
30      public void run() {
31          try {
32              // 为 DiscoveryResponse events 添加 DiscoveryListener
33              discovery.addDiscoveryListener(this);
34
35              while (true) {
36                  System.out.println("Sending a Discovery Message");
37                  // 寻找Peers,每个Peer最多反馈5个 。
38                  discovery.getRemoteAdvertisements(null, DiscoveryService.PEER,
39                                                      null, null, 5);
40
41                  // 等待一分钟
42                  try {
43                      Thread.sleep(60 * 1000);
44                  } catch(Exception e) {}
45
46              }
47          } catch(Exception e) {
48              e.printStackTrace();
49          }
50      }
51
52      // 为了实现 DiscoveryListener,我们必须定义这个方法来处理所反馈信息
53
54      public void discoveryEvent(DiscoveryEvent ev) {
55
56          DiscoveryResponseMsg res = ev.getResponse();
57          String name = "unknown";
58
59          // 获得Peers的反馈广告
60          PeerAdvertisement peerAdv = res.getPeerAdvertisement();
61
62          // 一些Peers不能反馈他们的 PeerAdvertisement
63          if (peerAdv != null) {
64              name = peerAdv.getName();
65          }
66
67          System.out.println ("Got a Discovery Response [" +
68                  res.getResponseCount()+ " elements] from peer : " +
69                              name);
70
71          // 输出发现的Peer
72          PeerAdvertisement adv = null;
73          Enumeration enum = res.getAdvertisements();
74
75          if (enum != null ) {
76              while (enum.hasMoreElements()) {
77                  adv = (PeerAdvertisement) enum.nextElement();
78                  System.out.println (" Peer name = " + adv.getName());
79              }
80          }
81      }
82
83      static public void main(String args[]) {
84          DiscoveryDemo myapp = new DiscoveryDemo();
85          myapp.startJxta();
86          myapp.run();
87      }
88  }
 
一个JXTA Peer 用getLocalAdvertisements()方法来检索本地缓存中的Advertisements,如果想发现其他的 Advertisements,就必须用getRemoteAdvertisements(),来发送一个Discovery Query Message给别的Peers。Discovery Query Messages能发送给一个Peer,但也能发送到一个JXTA的网络上。在J2SE的平台上,Discovery Query Messages还可以发给一个rendezvous。如果这个Peer还没有连接到这个rendezvous上,那么Discovery Query Message将只有通过多次的尝试发送到本地的子网。一旦这个Peer已经连接上了一个rendezvous,那么Discovery Query Message也将被传送给这个rendezvous peer。一个Peer在Discovery Query Message里包括它自己的广告,完成一个公告或者是自动的发现机制。
有两个方法来接收DiscoveryResponse Message,你可以等候一个或多个Peer来响应DiscoveryResponse Message,并且调用方法getLocalAdvertisements()来检索已经被发现的任何结果,并添加到本地的缓存中的广告。添加一个 Discovery Listener来通知发现的Peer,当discovery events被接收时,调用discoveryEvent()方法。这里有两个方法添加Discovery Listener,一个是直接的addDiscoveryListener()(参考本程序Line33),另一个是通过getRemoteAdvertisements()方法。本例用的是第一种方法,如果采用第二种方法,可以将下程序的Line38~39写成:
discovery.getRemoteAdvertisements(null, DiscoveryService.PEER,null,null,5,this);
并去掉Line33行程序即可。
如果你在运行上面的程序时,没有收到任何的Discovery Response,L!你很有可能没有正确的配置好你的JXTA平台环境。请删除.jxta目录下的PlatformConfig文件,并重新运行程序。
12.小结
    本文讲述了JXTA平台如何处理发现其他Peer的有关事宜以及JXTA的Java参考实现中提供的如何给其他Peer发送Discovery请求消息并处理返回的响应。还提到了利用Java参考实现中提供的Discovery接口及实现如何在本地或远程发布Advertisement。
当然,上面所介绍的PDP只是JXTA核心协议的一部分,还有的一些协议将在以后的文章中再介绍,呵呵……:)
 
注:在JXTA里,Advertisement(广告)相当于人类社会中的名片,在JXTA网络中的所有资源都通过广告来描述,用XML语言来描述Advertisement。

你可能感兴趣的:(JXTA核心协议之对等机发现协议(PDP))