JXTA, P2P编程技术例程(3)

类别:Java 点击:0 评论:0 推荐:
 

质数查询客户端

这个客户端的目的是尽可能的将计算量分布到其它PEER上.考虑用户要获得1到10000之间的质数, 一个peer接到这个消息的时候, 它就需要决定要分给几个peer来做这件事情。.因此,它需要不断的去发现那些通告自己有质数服务的peer,并为它们的通告提供一个缓冲来保存. 例如一个peer有另外10个peer和它一起工作, 那么它可能在第一个消息中以1作为LOW_INT, 1000作HIGH_INT, 在另外一个消息中,以1001作为LOW_INT, 2000作为HIGH_INT,以此类推. 最后, 客户端将打开一个管道通往这10个peer,然后分别向他们传输消息。

客户端的skeleton看起和服务端的差不多, 同样是先初始化Net Peer Group,然后获得GROUP的发现服务和管道服务。.

 

Listing 16.10 PrimeClient

package primecruncher;

import net.jxta.peergroup.PeerGroup;

import net.jxta.peergroup.PeerGroupFactory;

import net.jxta.discovery.DiscoveryService;

import net.jxta.discovery.DiscoveryListener;

import net.jxta.discovery.DiscoveryEvent;

import net.jxta.pipe.PipeService;

import net.jxta.pipe.OutputPipe;

import net.jxta.pipe.PipeID;

import net.jxta.exception.PeerGroupException;

import net.jxta.protocol.DiscoveryResponseMsg;

import net.jxta.protocol.ModuleSpecAdvertisement;

import net.jxta.protocol.PipeAdvertisement;

import net.jxta.document.StructuredTextDocument;

import net.jxta.document.MimeMediaType;

import net.jxta.document.TextElement;

import net.jxta.document.AdvertisementFactory;

import net.jxta.id.IDFactory;

import net.jxta.endpoint.Message;

import java.util.Enumeration;

import java.io.StringWriter;

import java.io.IOException;

import java.net.URL;

import java.net.MalformedURLException;

import java.net.UnknownServiceException;

import java.util.HashSet;

import java.util.Set;

public class PrimeClient implements DiscoveryListener {

        private static PeerGroup group;

        private static DiscoveryService discoSvc;

        private static PipeService pipeSvc;

        private OutputPipe outputPipe;

        private Set adverts = new HashSet();

        public PrimeClient() {

        }

        public static void main(String[] argv) {

               Client cl = new Client();

               cl.startJxta();

               cl.doDiscovery();

        }

        public int[] processPrimes(int low, int high) {

        }

        private void startJxta() {

               try {

                       group = PeerGroupFactory.newNetPeerGroup();

                       discoSvc = group.getDiscoveryService();

                       pipeSvc = group.getPipeService();

               } catch (PeerGroupException e) {

                       System.out.println("Can't create net peer group: " +

                               e.getMessage());

                       System.exit(-1);

               }

        }

        private void doDiscovery() {

 

        }

}

虽然PrimePeer的关键责任是通告它自己的服务和处理收到的消息, PrimeClient 同时必须参与到服务发现过程中)

 doDiscovery()方法初始化了服务发现。 首先,peer调查自己缓冲,在质数计算module的说明中去发现与名字属性想匹配的通告

Listing 16.11 Performing Local Discovery

        System.out.println("Starting service discovery...");

        System.out.println("Searching local cache for " +

               ServiceConstants.SPEC_NAME + " advertisements");

        Enumeration res = null;

        try {

                res = discoSvc.getLocalAdvertisements(DiscoveryService.ADV,

                      "Name", ServiceConstants.SPEC_NAME);

        } catch (IOException e) {

               System.out.println("IO Exception.");

        }

        if (res != null) {

               while (res.hasMoreElements()) {

                       processAdv((ModuleSpecAdvertisement)res.nextElement());

               }

}

然后,peer初始化远程通告发现, 远程发现意味着发现请求将在JXTA网络中传播,当合适的通告被发现后, 就发出回应。 因此, 远程发现是一个异步的过程,我们传递DiscoveryListener 作为一个值(argument)到DiscoveryService 的 getRemoteAdvertisements()方法中。 另外,我们还必须说明我们需要从每个peer中得到的通告数目。

一旦远程发现被初始化了, 被发现的通告就被存储在本地的通告cache中, 这样,下一次这个peer开始工作的时候, 它将从这个缓冲中发现通告。

Listing 16.12 Initiating Remote Service Discovery

        System.out.println("Starting remote discovery...");

        discoSvc.getRemoteAdvertisements(null, DiscoveryService.ADV,

                "Name", ServiceConstants.SPEC_NAME, 1, this);

}

DiscoveryListener 说明了discoveryEvent()方法在每次被调用的时候将发现一个匹配标准的通告,一个DiscoveryEvent 包括了一个DiscoveryReponseMsg, 它包含一个在远程发现中发现的实际的通告。 我们获得了这些通告的枚举 然后对每个进行操作。

Listing 16.13 Implementing a DiscoveryListener

        public void discoveryEvent(DiscoveryEvent event) {

               System.out.println("DiscoveryEvent called");

               DiscoveryResponseMsg  mes = event.getResponse();

               //these contain the responses found

               Enumeration res = mes.getResponses();

               if (res != null) {

                      while (res.hasMoreElements()) {

                              processAdv((ModuleSpecAdvertisement) res.nextElement());

                      }

               }

}

processAdv()方法非常简单,它插入每个ModuleSpecAdvertisement到一个集合中,这个集合保证没有存储重复的通告, 这个集合作为module的说明通告的缓冲被使用。

        private void processAdv(ModuleSpecAdvertisement ad) {

               adverts.add(ad);

}

本文地址:http://com.8s8s.com/it/it16674.htm