您的位置:首页 > 其它

JXTA的一个例子[加了注释]

2007-07-25 14:37 302 查看
这是一个简单的应用JXTA的客户/服务器结构的例子,服务器端创建监听线程,客户端主动连接一次。所有代码非常简洁的说明了JXTA的C/S应用的设计框架,原例子是在http://www.jxta.org/Tutorials.html,我在本机和局域网内已调试通过,并加了注释,有兴趣的朋友看看吧。
需要引用的jar包有三个:jxta.jar,log4j.jar,bcprov-jdk14.jar
服务器端

package com.solo.server;

import java.io.*;

import net.jxta.discovery.*;
import net.jxta.document.*;
import net.jxta.endpoint.*;
import net.jxta.exception.*;
import net.jxta.id.*;
import net.jxta.peergroup.*;
import net.jxta.pipe.*;
import net.jxta.platform.*;
import net.jxta.protocol.*;

public class SoloServer {

  static PeerGroup group = null;
  static PeerGroupAdvertisement groupAdvertisement = null;
  private DiscoveryService discovery;
  private PipeService pipes;
  private InputPipe myPipe; // 输入管道,从客户端来的
  private Message msg;  // 收到的消息
  private ID gid;

  public static void main(String[] args) {
    SoloServer myServer = new SoloServer();
    System.out.println("Starting service peer...");
    System.out.println(System.getProperty("user.dir"));
    myServer.startJxta();
    System.out.println("Good Bye ....");
    System.exit(0);
  }

  private void startJxta() {
    try {
      // 开始,要使用默认的JXTA组
      group = PeerGroupFactory.newNetPeerGroup();
    }
    catch (PeerGroupException ex) {
      System.out.println("fatal error : group creation failure");
      ex.printStackTrace();
      System.exit(1);
    }
    // 得到默认组的通告
    groupAdvertisement = group.getPeerGroupAdvertisement();
    // 获取该通告的发现服务
    System.out.println("Getting DiscoveryService...");
    discovery = group.getDiscoveryService();
    // 获取该通告的管道服务
    System.out.println("Getting PipeService...");
    pipes = group.getPipeService();

    startServer();
  }

  private void startServer() {
    System.out.println("Start the Server daemon...");

    // 读该组的ID
    gid = group.getPeerGroupID();

    try {
      // 创建一个模块化的简单的通告,此通告仅仅用来表示该服务的存在。
      // 如果端点要访问该服务,还得创建一个指定的通告,来关联服务。
      ModuleClassAdvertisement mcadv = (ModuleClassAdvertisement)
          AdvertisementFactory.newAdvertisement(ModuleClassAdvertisement.
                                                getAdvertisementType());
      mcadv.setName("JXTAMOD:JXTA-SOLO-XDS-CN");
      mcadv.setDescription("SOLO SERVER FOR SOLO-CN WITH JXTA FRAMEWORK.");

      ModuleClassID mcID = IDFactory.newModuleClassID();
      mcadv.setModuleClassID(mcID);

      discovery.publish(mcadv);
      discovery.remotePublish(mcadv);

      // 创建一个指定的通告,使得端点可以与服务相连。
      // 该通告包含端点连接服务所需要的所有信息,
      // 例如它包含一个端点用来与服务关联的输入管道数据
      ModuleSpecAdvertisement mdadv = (ModuleSpecAdvertisement)
          AdvertisementFactory.newAdvertisement(ModuleSpecAdvertisement.
                                                getAdvertisementType());
      // 填充相关的信息
      mdadv.setName("JXTASPEC:JXTA-SOLO-XDS-CN");
      mdadv.setVersion("VERISON 1.0");
      mdadv.setCreator("solo.com");
      mdadv.setModuleSpecID(IDFactory.newModuleSpecID(mcID));
      mdadv.setSpecURI("http://www.solo_xds.cn");

      // 创建输入管道,端点必须使用同样的管道才能与服务通话,
      // 当端点发现服务通告时,提取此管道数据来创建它的输出管道,
      // 我们采用从文件中读取该管道信息的原因是为了保证每次创建的都是相同的管道。
      System.out.println("Reading in PipeService.adv....");
      PipeAdvertisement pipeadv = null;
      try {
        FileInputStream is = new FileInputStream("pipeserver.adv");
        XMLDocument document = (XMLDocument) StructuredDocumentFactory.
            newStructuredDocument(MimeMediaType.XMLUTF8, is);
        pipeadv = (PipeAdvertisement)
            AdvertisementFactory.newAdvertisement(
                document);
        is.close();
      }
      catch (Exception e) {
        System.out.println("failed to read/parse pipe advertisement");
        e.printStackTrace();
        System.exit( -1);
      }
      // 将此管道的通告保存在指定的服务通告中,
      // 每次端点与服务联系时都可得到此通告。
      mdadv.setPipeAdvertisement(pipeadv);

      // 显示一下服务通告
      StructuredTextDocument doc = (StructuredTextDocument)
          mdadv.getDocument(MimeMediaType.XMLUTF8);
      StringWriter out = new StringWriter();
      doc.sendToWriter(out);
      System.out.println(out.toString());
      out.close();

      // 好了,通告已经建立,发布到本地缓存和默认组的缓存中。
      discovery.publish(mdadv);
      discovery.remotePublish(mdadv);

      //开始服务了,准备好输入管道吧。
      myPipe = pipes.createInputPipe(pipeadv);
    }
    catch (Exception ex) {
      ex.printStackTrace();
      System.out.println("Server: Error publishing the module");
    }

    // listen死循环,不能停止
    while (true) {
      System.out.println("Waiting for client messages to arrive...");
      try {
        // listen pipe
        msg = myPipe.waitForMessage();
      }
      catch (Exception e) {
        myPipe.close();
        System.out.println("Server: Error listening for message");
        return;
      }

      String ip = null;
      // 读取端点传来的信息
      try {
        Message.ElementIterator en = msg.getMessageElements();
        if (!en.hasNext()) {
          return;
        }
        MessageElement msgElement = msg.getMessageElement(null, "DataTag");
        if (msgElement.toString() != null) {
          ip = msgElement.toString();
        }
        if (ip != null) {
          // 显示吧
          System.out.println("Server: receive message: " + ip);
        }
        else {
          System.out.println("Server: error could not find the tag");
        }
      }
      catch (Exception ex) {
        System.out.println("Server: error receiving message");
      }
    }
  }
}


客户端

package com.solo.client;

import java.io.*;
import java.util.*;

import net.jxta.discovery.*;
import net.jxta.document.*;
import net.jxta.endpoint.*;
import net.jxta.exception.*;
import net.jxta.peergroup.*;
import net.jxta.pipe.*;
import net.jxta.protocol.*;

public class SoloClient {
  static PeerGroup netPeerGroup = null;
  static PeerGroupAdvertisement groupAdvertisement = null;
  private DiscoveryService discovery;
  private PipeService pipes;
  private OutputPipe myPipe; // 输出管道,到服务的
  private Message msg;

  public SoloClient() {
  }

  public static void main(String[] args) {
    SoloClient myClient = new SoloClient();
    System.out.println("Starting Client peer ....");
    myClient.startJxta();
    System.out.println("Good Bye ....");
    System.exit(0);
  }

  /**
   * startJxta
   */
  private void startJxta() {
    try {
      // 创建默认的JXTA组。
      netPeerGroup = PeerGroupFactory.newNetPeerGroup();
    }
    catch (PeerGroupException e) {
      System.out.println("fatal error : group creation failure");
      e.printStackTrace();
      System.exit(1);
    }

    // 获取该组通告
    groupAdvertisement = netPeerGroup.getPeerGroupAdvertisement();
    // 获取该组发现服务
    System.out.println("Getting DiscoveryService");
    discovery = netPeerGroup.getDiscoveryService();
    // 获取该组管道服务
    System.out.println("Getting PipeService");
    pipes = netPeerGroup.getPipeService();
    startClient();

  }

  private void startClient() {

    System.out.println("Start the Client");

    // 找到服务
    System.out.println("searching for the JXTA-SOLO-XDS-CN Service advertisement");
    Enumeration en = null;
    while (true) {
      try {

        // 在本地的缓存中查找服务(JXTA-SOLO-XDS-CN)
        en = discovery.getLocalAdvertisements(DiscoveryService.ADV
                                              , "Name"
                                              , "JXTASPEC:JXTA-SOLO-XDS-CN");

        // 找到就好
        if ( (en != null) && en.hasMoreElements()) {
          break;
        }

        // 本地没有,只好根据服务名称远程搜索
        discovery.getRemoteAdvertisements(null
                                          , DiscoveryService.ADV
                                          , "Name"
                                          , "JXTASPEC:JXTA-SOLO-XDS-CN", 1, null);

        // 发现过程是异步的,我们不知道需要多长时间
        try {
          Thread.sleep(2000);
        }
        catch (Exception e) {}

      }
      catch (IOException e) {
        // 啥也没找到,继续
      }
      //显示点吧
      System.out.print(".");
    }

    System.out.println("we found the service advertisement");

    // 找到以后,得到特殊服务的通告
    ModuleSpecAdvertisement mdsadv = (ModuleSpecAdvertisement) en.nextElement();
    try {

      // 显示一下通告而已
      StructuredTextDocument doc = (StructuredTextDocument)
          mdsadv.getDocument(MimeMediaType.TEXT_DEFAULTENCODING);

      StringWriter out = new StringWriter();
      doc.sendToWriter(out);
      System.out.println(out.toString());
      out.close();

      // 根据获取的通告,获取管道
      PipeAdvertisement pipeadv = mdsadv.getPipeAdvertisement();

      // 用上面的通道,通知服务创建输出通道了,试着创建3次。
      for (int i = 0; i < 3; i++) {
        myPipe = pipes.createOutputPipe(pipeadv, 10000);
      }

      // 要说的话
      String data = "我靠,成功啦!!!";

      // 组织成消息
      msg = new Message();
      StringMessageElement sme = new StringMessageElement("DataTag", data, null);
      msg.addMessageElement(null, sme);

      // 通过管道发送吧
      myPipe.send(msg);
      System.out.println("message /"" + data + "/" sent to the Server");
    }
    catch (Exception ex) {
      ex.printStackTrace();
      System.out.println("Client: Error sending message to the service");
    }
  }

}


==========================================
在服务器端的根目录下还需要一个叫作pipeserver.adv的管道通告文件,这个文件的作用是使得每次服务启动时创建的都是同一个管道服务。

<?xml version="1.0"?>

<!DOCTYPE jxta:PipeAdvertisement>

<jxta:PipeAdvertisement xmlns:jxta="http://jxta.org">
  <Id>
    urn:jxta:uuid-9CCCDF5AD8154D3D87A391210404E59BE4B888209A2241A4A162A10916074A9504
  </Id>
  <Type>JxtaUnicast</Type>
  <Name>JXTA-SOLO-XDS-CN</Name>
</jxta:PipeAdvertisement>


第一次启动服务器和客户端时需要输入节点名和密码,随便输入就可以了。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: