`
cuizhenfu#gmail.com
  • 浏览: 66269 次
  • 性别: Icon_minigender_1
  • 来自: 北京
文章分类
社区版块
存档分类
最新评论

转载对等机发现协议PDP(Peer Discovery Protocol)

阅读更多
http://www.lmtw.com/p2p/Tcom/200510/16080.html

PDP主要用来发布自己的广告信息,和查找其他Peer的广告。

如前篇文章所述,Advertisement是Peer之间各种信息交流的基本单元,发现其他Peer及其他Peer及其资源的问题就转换为发现描述各资源的Advertisement的问题,只要找到对应的Advertisement,就相当于找到了该资源。

PDP定义了发现其他Peer和资源的协议,该协议包括两个方面,一方面用于请求获得其他Peer的Advertisement;另一方面用于响应其他Peer的这种请求。

1.PDP的消息格式

PDP只由两种格式构成,他们是:

用于发现Advertisement的请求格式;

用于响应请求的响应格式。

这两种消息,即发现请求消息和发现响应消息,定义了两个Peer之间互相发现对方所需的所有元素。

虽然discovery消息定义了请求和对应的响应,但一定要注意,有时响应可能收不到,有很多原因会造成对应某请求的响应收不到,比方说该请求未能生成任何结果或者响应超过一定数额被请求对方忽略了(参考下程序Line 62~65)。

2.Discovery Query Message

一个Peer想要寻找某种Advertisement时,就会发出Discovery Query Message(Discovery请求消息),这个请求消息的格式如下:

 

 

xml 代码
 
  1. <?xml version =”1.0” encoding =”UTF-8”?>  
  2.   
  3. <jxta: DiscoveryQuery>  
  4.   
  5. <PeerAdv></PeerAdv>  
  6.   
  7. <Type></Type>  
  8.   
  9. <Attr></Attr>  
  10.   
  11. <Value></Value>  
  12.   
  13. <Threshold></Threshold>  
  14.   
  15. </jxta: DiscoveryQuery >  

 

PeerAdv:可选元素,表示Peer的ID,如果设置为null,则转向Peer所在PeerGroup。

Type:有三种类型,PEER(0),GROUP(1),ADV(2)。

Attr和Value:都是可选元素,规定响应中的Advertisement需要满足的条件。前者指明Advertisement中的元素名,后者指明元素的值。只有满足这样的条件的Advertisement才能作为该请求的响应。

Threshold:也是个可选元素,该元素包括一个数字,指明最多可以接受多少数目的Advertisement。发出一个请求后,可能会有很多响应,指定了最多接受数目后,多余的会忽略掉。(参考下程序Line38~39)

特殊情况:

当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 代码
 
  1. <?xml version =”1.0” encoding =”UTF-8”?>  
  2.   
  3. <jxta: DiscoveryQuery>  
  4.   
  5. <Type></Type>  
  6.   
  7. <Count></Count >  
  8.   
  9. <Attr></Attr>  
  10.   
  11. <Value></Value>  
  12.   
  13. <PeerAdv></PeerAdv>  
  14.   
  15. <Response Expiration =”expiration time”>  
  16.   
  17. …  
  18.   
  19. </Response>  
  20.   
  21. </jxta: DiscoveryQuery >  

 

 

Type:与Discovery Query Message中的Type元素一样,只有三种类型:PEER(0),GROUP(1),ADV(2)。

Count:一个包含integer值的可选元素,代表Message中响应元素的总数目。

Attr/Value:一对可选元素,与Discovery Query Message中的值相同,指明此响应产生时对应的原始搜索条件。

PeerAdv:一个可选元素,包含提供响应的Peer的Peer Message。

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 Service提供的方法来发送Discovery Query Message甚至不需要开发人员创建和发布DiscoveryQuery对象。

5.DiscoveryListener接口

发现discovery请求后,接到响应时应用程序需要获得通知以便取得响应中的Advertisement。在Java参考实现中,可以给 Discovery Service注册一个listener对象,当Discovery Response Messages到达时可以通过DiscoveryService获得通知。关于listener在Java中的作用,我在这里就不再多说了,如果不是很 懂的话,找本Java的基础书看看吧L!

每次DiscoveryService实例收到Discovery Response Message,都会调用该listener的discoveryEvent方法,并传递事件本身,事件中包括了响应的细节。但 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:

java 代码
  1. 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:发布有本地发布和远程发布。

本地发布方法有:

java 代码
 
  1. public void publish (Advertisement adv, int type)throws IOException;  
  2.   
  3. public void publish (Advertisement adv,int type,long lifetime,long lifetimeforOhers)throws IOException;   

远程发布方法有:

java 代码
 
  1. public void remotePublish (Advertisement adv, int type);  
  2.   
  3. public void remotePublish (Advertisement adv, int type, long lifetime);  

还是先用一个例子来说明吧!:)这个例子用来说明怎样发现网络上的其他JXTA Peers。
11.应用实例
Source Code: DiscoveryDemo.java
 

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.                                                       nullnull5);  
  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。

分享到:
评论

相关推荐

Global site tag (gtag.js) - Google Analytics