0

この記事について: http://java.sun.com/developer/technicalArticles/tools/JavaSpaces/は、JavaSpaces クライアントを実行する方法のチュートリアルです。これらのクラスを Eclipse で作成し、Launch-All スクリプトと Run example を開始しました。できます。その後、これらのクラスを実行可能な jar (JavaSpaceClient.jar) にエクスポートし、次のコマンドでその jar を試しました。 java -jar JavaSpaceClient.jar 正常に動作し、結果が得られます。スペースにメッセージを書き込む... スペースからメッセージを読み取る... 読み取られるメッセージは次のとおりです: Здраво JavaSpace свете!

私の問題は、このjarファイルを他のLANコンピューターに移動すると、同じコマンドを入力するとエラーが表示されることです。エラーは次のとおりです。

cica@cica-System-Name:~/Desktop$ java -jar JavaSpaceClient.jar 
Searching for a JavaSpace...
Jul 27, 2011 11:20:54 PM net.jini.discovery.LookupDiscovery$UnicastDiscoveryTask run
INFO: exception occurred during unicast discovery to biske-Inspiron-1525:4160 with constraints InvocationConstraints[reqs: {}, prefs: {}]
java.net.UnknownHostException: biske-Inspiron-1525
at java.net.AbstractPlainSocketImpl.connect(AbstractPlainSocketImpl.java:175)
at java.net.SocksSocketImpl.connect(SocksSocketImpl.java:384)
at java.net.Socket.connect(Socket.java:546)
at java.net.Socket.connect(Socket.java:495)
at com.sun.jini.discovery.internal.MultiIPDiscovery.getSingleResponse(MultiIPDiscovery.java:134)
at com.sun.jini.discovery.internal.MultiIPDiscovery.getResponse(MultiIPDiscovery.java:75)
at net.jini.discovery.LookupDiscovery$UnicastDiscoveryTask.run(LookupDiscovery.java:1756)
at net.jini.discovery.LookupDiscovery$DecodeAnnouncementTask.run(LookupDiscovery.java:1599)
at com.sun.jini.thread.TaskManager$TaskThread.run(TaskManager.java:331)

「JavaSpace を検索しています...」と書くだけで、しばらくするとこれらのエラー メッセージが出力されます。誰かがこのエラーで私を助けることができますか?

編集:発見のために、インターネットで見つけた LookupDiscovery クラスを使用しています:

import java.io.IOException;

import java.rmi.RemoteException;

import net.jini.core.lookup.ServiceRegistrar;
import net.jini.core.lookup.ServiceTemplate;

import net.jini.discovery.LookupDiscovery;
import net.jini.discovery.DiscoveryListener;
import net.jini.discovery.DiscoveryEvent;

/**
   A class which supports a simple JINI multicast lookup.  It doesn't register
   with any ServiceRegistrars it simply interrogates each one that's
   discovered for a ServiceItem associated with the passed interface class.
   i.e. The service needs to already have registered because we won't notice
   new arrivals. [ServiceRegistrar is the interface implemented by JINI
   lookup services].

   @todo Be more dynamic in our lookups - see above

   @author  Dan Creswell (dan@dancres.org)
   @version 1.00, 7/9/2003
 */
public class Lookup implements DiscoveryListener {
    private ServiceTemplate theTemplate;
    private LookupDiscovery theDiscoverer;

    private Object theProxy;

    /**
       @param aServiceInterface the class of the type of service you are
       looking for.  Class is usually an interface class.
     */
    public Lookup(Class aServiceInterface) {
        Class[] myServiceTypes = new Class[] {aServiceInterface};
        theTemplate = new ServiceTemplate(null, myServiceTypes, null);
    }

    /**
       Having created a Lookup (which means it now knows what type of service
       you require), invoke this method to attempt to locate a service
       of that type.  The result should be cast to the interface of the
       service you originally specified to the constructor.

       @return proxy for the service type you requested - could be an rmi
       stub or an intelligent proxy.
     */
    Object getService() {
        synchronized(this) {
            if (theDiscoverer == null) {

                try {
                    theDiscoverer =
                        new LookupDiscovery(LookupDiscovery.ALL_GROUPS);
                    theDiscoverer.addDiscoveryListener(this);
                } catch (IOException anIOE) {
                    System.err.println("Failed to init lookup");
                    anIOE.printStackTrace(System.err);
                }
            }
        }

        return waitForProxy();
    }

    /**
       Location of a service causes the creation of some threads.  Call this
       method to shut those threads down either before exiting or after a
       proxy has been returned from getService().
     */
    void terminate() {
        synchronized(this) {
            if (theDiscoverer != null)
                theDiscoverer.terminate();
        }
    }

    /**
       Caller of getService ends up here, blocked until we find a proxy.

       @return the newly downloaded proxy
     */
    private Object waitForProxy() {
        synchronized(this) {
            while (theProxy == null) {

                try {
                    wait();
                } catch (InterruptedException anIE) {
                }
            }

            return theProxy;
        }
    }

    /**
       Invoked to inform a blocked client waiting in waitForProxy that
       one is now available.

       @param aProxy the newly downloaded proxy
     */
    private void signalGotProxy(Object aProxy) {
        synchronized(this) {
            if (theProxy == null) {
                theProxy = aProxy;
                notify();
            }
        }
    }

    /**
       Everytime a new ServiceRegistrar is found, we will be called back on
       this interface with a reference to it.  We then ask it for a service
       instance of the type specified in our constructor.
     */
    public void discovered(DiscoveryEvent anEvent) {
        synchronized(this) {
            if (theProxy != null)
                return;
        }

        ServiceRegistrar[] myRegs = anEvent.getRegistrars();

        for (int i = 0; i < myRegs.length; i++) {
            ServiceRegistrar myReg = myRegs[i];

            Object myProxy = null;

            try {
                myProxy = myReg.lookup(theTemplate);

                if (myProxy != null) {
                    signalGotProxy(myProxy);
                    break;
                }
            } catch (RemoteException anRE) {
                System.err.println("ServiceRegistrar barfed");
                anRE.printStackTrace(System.err);
            }
        }
    }

    /**
       When a ServiceRegistrar "disappears" due to network partition etc.
       we will be advised via a call to this method - as we only care about
       new ServiceRegistrars, we do nothing here.
     */
    public void discarded(DiscoveryEvent anEvent) {
    }
}

私のクライアント プログラムは、MessageEntry を書き込む JavaSpaces サービスを検索し、メッセージを取得して出力しようとします。クライアントプログラムは次のとおりです。

import net.jini.space.JavaSpace;

public class SpaceClient {
   public static void main(String argv[]) {
      try {
         MessageEntry msg = new MessageEntry();
         msg.content = "Hello JavaSpaces wordls!";
         System.out.println("Searching for JavaSpaces...");
         Lookup finder = new Lookup(JavaSpace.class);
         JavaSpace space = (JavaSpace) finder.getService();
         System.out.println("JavaSpaces discovered.");
         System.out.println("Writing into JavaSpaces...");
         space.write(msg, null, 60*60*1000);
         MessageEntry template = new MessageEntry();
         System.out.println("Reading message from JavaSpaces...");
         MessageEntry result = (MessageEntry) space.read(template, null, Long.MAX_VALUE);
         System.out.println("Message: "+result.content);
      } catch(Exception e) {
         e.printStackTrace();
      }
   }
}

そしてもちろん、これは MessageEntry クラスです:

import net.jini.core.entry.*;

public class MessageEntry implements Entry {
   public String content;

   public MessageEntry() {
   }

   public MessageEntry(String content) {
     this.content = content;
   }

   public String toString() {
     return "MessageContent: " + content;
   }
}

EDIT2: 2 台の Windows コンピューターで検出を行いました。その後、Windows - Ubuntu の組み合わせを試してみましたが、うまくいきません。多分いくつかのネットワークの問題がありますか?お互いにpingを実行すると、すべて問題ありません。UbuntuにDNSの問題があるかもしれません..

EDIT3: Windows - Ubuntu の組み合わせは、JavaSpaces サービスが Windows で起動され、クライアント プログラムが Ubuntu にある場合に機能します。逆に実行しようとすると、Ubuntu で JavaSpaces サービスを実行し、Windows でクライアントを実行するとエラーが発生します。明らかに、Ubuntuにはいくつかの問題があります。Ubuntu には、デフォルトでインストールされている OpenJDK がインストールされています。Oracle JDK をインストールし、JAVA_HOME を設定して、JAVA_HOME/bin を PATH 変数に入れました。異なるバージョンのJavaに問題があるのではないかと思います。おそらく、正しいバージョンを使用していないのでしょう。

4

3 に答える 3

2

(ポート 4160 のホスト biske-Inspiron-1525 で) 実行しているサービス レジストラーが、そのホスト名を誤って (ドメイン名なしで) 検出し、短いホスト名でアナウンスを送信している可能性があります。したがって、サービス レジストラを検出した後、クライアントがサービス レジストラに接続しようとしても、別のドメインにある場合、ホスト名を解決できない可能性があります。

サービス レジストラーが正しいホスト名で実行されていることを確認するには、次のコマンド ライン属性を使用してサービス レジストラーを起動してみてください。

-Dcom.sun.jini.reggie.unicastDiscoveryHost="biske-Inspiron-1525.and.its.domain"
于 2011-08-24T10:11:38.503 に答える
1

特定のホストとポートに対してユニキャスト検出を行っているようですが、そのホストを検索できません。

DNS で biske-Inspiron-1525 という名前を解決できると仮定すると、「:4160」の部分を削除して、ユニキャスト ルックアップが成功するかどうかを確認します。

サービスを検索するために使用するコードの例を次に示します。ServiceDiscoveryListener を実装し、その方法でサービス ディスカバリを処理するため、もう少し複雑です。私は実際にサービスのリストを保持し、1 つが失敗したときに動的に切り替えますが、例からその部分を取り除きました。あとで説明する Jini の Configuration 部分も使用しています。ここで使用しているサービス インターフェイスは「TheService」と呼ばれます。

public class JiniClient implements ServiceDiscoveryListener {

private TheService service = null;

private Class[] serviceClasses;
private ServiceTemplate serviceTemplate;

public JiniClient(String[] configFiles) throws ConfigurationException {

    Configuration config = ConfigurationProvider.getInstance(configFiles,
            getClass().getClassLoader());


    // Set the security manager
    System.setSecurityManager(new RMISecurityManager());        

    // Define the service we are interested in.
    serviceClasses = new Class[] {TheService.class};
    serviceTemplate = new ServiceTemplate(null, serviceClasses, null);

    // Build a cache of all discovered services and monitor changes
    ServiceDiscoveryManager serviceMgr = null;

    DiscoveryManagement mgr = null;
    try {
        mgr = (DiscoveryManagement)config.getEntry(
                getClass().getName(), // component
                "discoveryManager",                 // name
                DiscoveryManagement.class);          // type

        if (null == mgr) {
            throw new ConfigurationException("entry for component " +
                    getClass().getName() + " name " +
                    "discoveryManager must be non-null");
        }
    } catch (Exception e) {
        /* This will catch both NoSuchEntryException and 
         * ConfigurationException. Putting them both
         * below just to make that clear.
         */
        if( (e instanceof NoSuchEntryException) || 
                (e instanceof ConfigurationException)) {
            // default value
            try {
                System.err.println("Warning, using default multicast discover.");
                mgr = new LookupDiscoveryManager(LookupDiscovery.ALL_GROUPS,
                        null,  // unicast locators
                        null); // DiscoveryListener
            } catch(IOException ioe) {
                e.printStackTrace();
        throw new RuntimeException("Unable to create lookup discovery manager: " + e.toString());
            }
        } 
    }

    try {
        serviceMgr = new ServiceDiscoveryManager(mgr, new LeaseRenewalManager());
    } catch (IOException e) {
        e.printStackTrace();
        throw new RuntimeException("Unable to create service discovery manager: " + e.toString());
    }

    try {
        serviceMgr.createLookupCache(serviceTemplate, 
                                                null,  // no filter
                                                this); // listener
    } catch(Exception e) {
        e.printStackTrace();
        throw new RuntimeException("Unable to create serviceCache: " + e.getMessage());
    }
}

public void serviceAdded(ServiceDiscoveryEvent evt) {
       /* Called when a service is discovered */
    ServiceItem postItem = evt.getPostEventServiceItem();
    //System.out.println("Service appeared: " +
    //         postItem.service.getClass().toString());

    if(postItem.service instanceof TheService) {
        /* You may be looking for multiple services. 
                     * The serviceAdded method will be called for each
                     * so you can use instanceof to figure out if 
                     * this is the one you want.
                     */
        service = (TheService)postItem.service;

    }       
}

public void serviceRemoved(ServiceDiscoveryEvent evt) {
/* This notifies you of when a service goes away. 
     * You could keep a list of services and then remove this 
     * service from the list. 
 */ 
}

public void serviceChanged(ServiceDiscoveryEvent evt) {
/* Likewise, this is called when a service changes in some way. */  

}

構成システムを使用すると、検出方法を動的に構成できるため、アプリを変更せずに特定のユニキャスト システムまたはマルチキャストを検出するように切り替えることができます。上記のオブジェクト コンストラクターに渡すことができるユニキャスト検出構成ファイルの例を次に示します。

import net.jini.core.discovery.LookupLocator;
import net.jini.discovery.LookupDiscoveryManager;
import net.jini.discovery.LookupDiscovery;

com.company.JiniClient {
    discoveryManager = new LookupDiscoveryManager(
        LookupDiscovery.ALL_GROUPS,
        new LookupLocator[] { new LookupLocator("jini://biske-Inspiron-1525.mycompany.com")},
        null,
        this); // the current config
}
于 2011-08-24T01:06:27.303 に答える
0

解決策を見つけました!それはDNSの問題でした。Ubuntu では、私の /etc/hosts ファイルは次のとおりでした。

192.168.1.3 biske-Inspiron-1525 # Added by NetworkManager
127.0.0.1   localhost.localdomain   localhost
::1 biske-Inspiron-1525 localhost6.localdomain6 localhost6
127.0.1.1   biske-Inspiron-1525

# The following lines are desirable for IPv6 capable hosts
::1     localhost ip6-localhost ip6-loopback
fe00::0 ip6-localnet
ff00::0 ip6-mcastprefix
ff02::1 ip6-allnodes
ff02::2 ip6-allrouters
ff02::3 ip6-allhosts

127.0.1.1 biske-Inspiron-1525を削除したところ、正常に動作するようになりました。ささいなことで、何百万もの私の神経が破壊されました:)

于 2011-09-22T14:44:39.297 に答える