java.rmi.ConnectException: 连接被拒绝,无法连接到主机:127.0.1.1;

58
    java.rmi.ConnectException: Connection refused to host: 127.0.1.1; nested exception is:
    java.net.ConnectException: Connection refused
    at sun.rmi.transport.tcp.TCPEndpoint.newSocket(TCPEndpoint.java:619)
    at sun.rmi.transport.tcp.TCPChannel.createConnection(TCPChannel.java:216)
    at sun.rmi.transport.tcp.TCPChannel.newConnection(TCPChannel.java:202)
    at sun.rmi.server.UnicastRef.invoke(UnicastRef.java:128)
    at java.rmi.server.RemoteObjectInvocationHandler.invokeRemoteMethod(RemoteObjectInvocationHandler.java:194)
    at java.rmi.server.RemoteObjectInvocationHandler.invoke(RemoteObjectInvocationHandler.java:148)
    at com.sun.proxy.$Proxy0.notifyMe(Unknown Source)
    at CallbackServerImpl.doCallback(CallbackServerImpl.java:149)
    at CallbackServerImpl.registerForCallback(CallbackServerImpl.java:70)
    at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
    at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:57)
    at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
    at java.lang.reflect.Method.invoke(Method.java:601)
    at sun.rmi.server.UnicastServerRef.dispatch(UnicastServerRef.java:322)
    at sun.rmi.transport.Transport$1.run(Transport.java:177)
    at sun.rmi.transport.Transport$1.run(Transport.java:174)
    at java.security.AccessController.doPrivileged(Native Method)
    at sun.rmi.transport.Transport.serviceCall(Transport.java:173)
    at sun.rmi.transport.tcp.TCPTransport.handleMessages(TCPTransport.java:553)
    at sun.rmi.transport.tcp.TCPTransport$ConnectionHandler.run0(TCPTransport.java:808)
    at sun.rmi.transport.tcp.TCPTransport$ConnectionHandler.run(TCPTransport.java:667)
    at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1145)
    at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:615)
    at java.lang.Thread.run(Thread.java:722)
    Caused by: java.net.ConnectException: Connection refused
    at java.net.PlainSocketImpl.socketConnect(Native Method)
    at java.net.AbstractPlainSocketImpl.doConnect(AbstractPlainSocketImpl.java:339)
    at java.net.AbstractPlainSocketImpl.connectToAddress(AbstractPlainSocketImpl.java:200)
    at java.net.AbstractPlainSocketImpl.connect(AbstractPlainSocketImpl.java:182)
    at java.net.SocksSocketImpl.connect(SocksSocketImpl.java:391)
    at java.net.Socket.connect(Socket.java:579)
    at java.net.Socket.connect(Socket.java:528)
    at java.net.Socket.<init>(Socket.java:425)
    at java.net.Socket.<init>(Socket.java:208)
    at sun.rmi.transport.proxy.RMIDirectSocketFactory.createSocket(RMIDirectSocketFactory.java:40)
    at sun.rmi.transport.proxy.RMIMasterSocketFactory.createSocket(RMIMasterSocketFactory.java:146)
    at sun.rmi.transport.tcp.TCPEndpoint.newSocket(TCPEndpoint.java:613)
    ... 23 more

当我尝试将远程客户端连接到我的服务器时,出现了此异常。在服务器和客户端中,rmi的registryUrl的hostName都是服务器的公共IP地址。我还尝试在服务器中放置localhost,但错误仍未改变。

我的java.policy已设置为授予所有端口的所有连接权限,并且在服务器或客户端中都没有启用防火墙。

有什么建议吗?

15个回答

55
这是RMI FAQ中的A.1项。您需要修复/etc/hosts文件或在服务器上设置java.rmi.server.hostname属性。

7
请问,您是如何解决这个问题的?我尝试使用以下命令:java HelloServer -Djava.rmi.server.hostname=192.168.1.5,但客户端无法找到服务器,出现了 java.rmi.ConnectException: Connection refused to host: 127.0.1.1; nested exception is: java.net.ConnectException: Connexion refusée 错误。 - researcher
1
@研究者 你需要在服务器的JVM上进行设置,而不是客户端。 - user207421
1
@researcher 你还需要在类名之前提供JVM参数,而不是之后。 - user207421
“服务器”是最初通过.export创建存根的骨架端,在服务器端修改隐式存根嵌入的IP,客户端调用:System.setProperty("java.rmi.server.hostname","1.2.3.4");,这意味着目标/骨架/服务器可被访问的IP地址。 - droid192
@researcher 经过无数个小时的尝试,定义服务器主机名终于成功了!我非常感激!谢谢。 - Patrick Bucher
2
@PatrickBucher 你提到的那个人只是提出了一个问题。你应该感谢的是我。 - user207421

20

问题解决

我遇到了完全相同的错误。当远程对象绑定到rmiregistry时,它会附加在回环IP地址上,如果你尝试从远程地址调用方法,显然会失败。为了解决这个问题,我们需要将java.rmi.server.hostname属性设置为其他设备可以通过网络访问您的rmiregistry的IP地址。当您尝试通过JVM设置参数时,它不起作用。我成功地解决了这个问题,只需在将对象绑定到rmiregistry之前在代码中添加以下行:

System.setProperty("java.rmi.server.hostname","192.168.1.2");

在这种情况下,绑定RMI Registry上远程对象的PC的本地网络上的IP地址是192.168.1.2。


5
如果你是指在命令行上使用 System.setProperty(),也就是说通过JVM来设置参数,那么它确实可以工作。但需要注意的是,在导出远程对象之前而不仅仅是绑定之前,你必须设置好该参数。 - user207421

13

你可以像下面这样使用LocateRegistry:

Registry rgsty = LocateRegistry.createRegistry(1888);
rgsty.rebind("hello", hello);

他在rebind()上没有收到错误。 - user207421
之前我使用了Naming.rebind()方法,遇到了与上述类似的错误。我按照您的代码建议进行了更改,在我的Naming.lookup()中添加了端口号,然后问题就解决了。非常感谢! - Lucky
@Lucky 这个答案没有提到 Naming.lookup() 方法。 - undefined

9

我在这个主题上找到了许多问答,但没有一个能帮助我 - 这是因为我的问题更基础(我不是网络专家 :))。 我在/etc/hosts中的IP地址是不正确的。 我尝试的包括以下内容:

CATALINA_OPTS:

CATALINA_OPTS="$CATALINA_OPTS -Djava.awt.headless=true -Xmx128M -server 
-Dcom.sun.management.jmxremote 
-Dcom.sun.management.jmxremote.port=7091 
-Dcom.sun.management.jmxremote.authenticate=false 
-Dcom.sun.management.jmxremote.ssl=false
-Djava.rmi.server.hostname=A.B.C.D"  #howeverI put the wrong ip here!

export CATALINA_OPTS

我的问题是很多月前我已更改了IP地址,但从未更新/etc/hosts文件。似乎jconsole默认使用hostname -i IP地址,在查看本地进程时也是如此。最好的解决方案是简单地更改/etc/hosts文件。

另一个可行的解决方案是从/sbin/ifconfig获取正确的IP地址,并在指定IP地址时使用该IP地址,例如在catalina.sh脚本中:

-Djava.rmi.server.hostname=A.B.C.D

4

如果您在Linux环境下运行,请打开文件/etc/hosts.allow并添加以下行:

ALL

通配符

还要检查/etc/hostname/etc/host,看看那里是否有什么问题。

我不得不更改我的/etc/host,从

127.0.0.1 localhost
127.0.1.1 AMK

to

127.0.0.1 localhost
127.0.0.1 AMK

现在一切都正常了。之前完全为空的文件/etc/hosts.allow中也写入了ALL

我不知道这有多安全。您需要阅读有关/etc/hosts.allow可能选项的更多信息,以执行需要一定安全性的操作。


谢谢,我刚刚修改了/etc/hosts文件,将我的本地主机名和localhost指向相同的IP地址,就像你展示的那样,现在一切都正常了。 - Davide

3

可能是因为在客户端尝试连接服务器之前,您的rmiregistry没有被创建,这会导致此异常。在Linux中,您可以使用"netstat"命令检查您的rmiregistry是否绑定在您在Java代码中分配的正确端口上。


使用这个堆栈跟踪不会引起此异常。 - user207421
4
现在我正在我的 Archlinux 系统上观察它,使用LocateRegistry.createRegistry(1099) 在我的服务器类中创建注册表而不是使用LocateRegistry.getRegistry()可以解决我的问题。 - alisianoi
它解决了另一个问题。它解决了“查找”时出现的“连接被拒绝”的问题。而这个问题是在调用远程方法时出现的“连接被拒绝”。 - user207421

2

如果您已尝试修改/etc/hosts并添加java.rmi.server.hostname属性,但注册表仍绑定到127.0.0.1,则问题可能是系统未通过代码明确设置该属性,而不是从JVM参数中获取相同的属性。

对我来说,问题在通过代码明确设置系统属性后得到解决。


注册表不会绑定到127.0.0.1。如果系统属性在命令行中无法工作,则操作不正确。 - user207421

1

在我的情况下,删除 /etc/hosts 文件中的 "::1" 后它就可以正常工作了。


1

我曾经遇到过完全相同的问题,我的问题是在etc/hosts文件中配置了来自两个不同网络的2个IP地址,如下所示。

10.xxx.x.xxx    localhost
192.xxx.x.xxx   localhost

这可能是因为其他设备在网络上访问rmiregistry时存在IP冲突。我删除了不必要的额外记录后,问题得以解决。因此,我的etc/hosts文件只有以下记录。
10.xxx.x.xxx    localhost

他们两个都错了。这些IP地址都应该映射到一个真实的主机名,并且还应该有另一个条目 127.0.0.1 localhost - user207421

0
在我的情况下,由于使用大学的电脑,我无法编辑hosts文件。
我通过在另一个端口(而不是1099)上运行rmiregistry来解决问题,命令如下:
rmiregistry <port>

然后在该端口上运行服务器。

这基本上是由于端口被占用而导致的错误。


如果端口已经被占用,你不会收到“连接被拒绝”的消息,而且除非你也调整了代码,否则将注册表更改为另一个端口并不能解决任何问题。自1996年起,1099端口被保留用于RMI注册表,因此无论所谓的进程是否已经在监听它,都是严重违规的。 - user207421

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接