在本文中:http://java.sun.com/developer/technicalArticles/tools/JavaSpaces/是一个如何运行JavaSpaces客户端的教程。我在Eclipse中编写了这些类,启动了Launch-All脚本和Run示例。有用。 之后我将这些类导出到可执行jar(JavaSpaceClient.jar)中并使用以下命令尝试该jar: java -jar JavaSpaceClient.jar 它工作正常,给我结果: 正在搜索JavaSpace ... 已经发现了JavaSpace。 在空间写一条消息...... 从空间阅读消息...... 阅读的信息是:ЗдравоJavaSpaceсвете!
我的问题是当我在我的其他局域网计算机上移动此jar文件时,当我输入相同的命令时,它会显示错误。这是错误:
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 ...”,过了一会儿打印出这些错误消息。 有人可以帮我解决这个错误吗?
编辑: 对于发现,我使用的是我在Internet上找到的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) {
}
}
我的客户端程序只是尝试搜索JavaSpaces服务写入MessageEntry,然后检索消息并将其打印出来。这是客户端程序:
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: 我在两台Windows计算机上做过发现。 之后我尝试了Windows - Ubuntu组合,它不起作用。也许有一些网络问题?当我互相ping一切都没关系。也许在Ubuntu上存在一些DNS问题..
EDIT3: Windows - 如果在Windows上启动JavaSpaces服务并且客户端程序在Ubuntu上,则Ubuntu组合有效。当我尝试反向时,在Ubuntu上运行JavaSpaces服务并在Windows上运行客户端时会发生错误。 显然Ubuntu存在一些问题。 Ubuntu默认安装了OpenJDK。我安装了Oracle JDK,并设置了JAVA_HOME并将JAVA_HOME / bin放入PATH变量中。我想也许不同版本的Java可能存在一些问题,也许我没有使用正确的版本。
答案 0 :(得分:2)
您正在运行的服务注册商(在端口4160上的主机biske-Inspiron-1525上)可能错误地发现了主机名(没有域名),因此发送带有短主机名的通知。因此,在发现服务注册商之后,客户端可能会尝试与服务注册商建立连接,如果主机名位于不同的域中,则无法解析主机名。
要确保服务注册程序使用正确的主机名运行,请尝试使用以下命令行属性启动它:
-Dcom.sun.jini.reggie.unicastDiscoveryHost="biske-Inspiron-1525.and.its.domain"
答案 1 :(得分:1)
您似乎正在对特定主机和端口进行单播发现,并且您无法查找该主机。
假设您可以使用DNS解析名称biske-Inspiron-1525,请尝试删除“:4160”部分,然后查看单播查找是否成功。
以下是我用于查找服务的代码示例。这有点复杂,因为我实现了ServiceDiscoveryListener并以这种方式处理服务发现。我实际上保留了一个服务列表,然后在一个服务器出现故障时动态切换,但我从该示例中剥离了该部分。我也在使用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
}
答案 2 :(得分: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 这一行,现在它运行正常。 小事被摧毁了我的神经:)