英文:
RMI Registry permission denied
问题
我正在尝试开始使用Java RMI,但是当我的组件尝试绑定(甚至连接)到rmiregistry时,我一直遇到错误。每当我尝试将任何东西绑定到rmiregistry时,都会出现java.rmi.ConnectIOException错误。我实在不知道我需要做什么来解决这个问题。
代码
服务器端
import java.rmi.registry.LocateRegistry;
import java.rmi.registry.Registry;
public class Server {
public static void main(String[] args) throws Exception {
HelloClass Obj = new HelloClass();
Registry registry = LocateRegistry.getRegistry();
registry.bind("Hello", Obj);
System.out.println("服务器已启动");
}
}
客户端
import java.rmi.registry.LocateRegistry;
import java.rmi.registry.Registry;
public class Client {
public static void main(String[] args) throws Exception{
Registry registry = LocateRegistry.getRegistry();
Hello hello = (Hello) registry.lookup("Hello");
String n = hello.Hello();
System.out.println(n);
}
}
Hello接口
import java.rmi.*;
public interface Hello extends Remote {
public String Hello() throws RemoteException;
}
HelloClass
import java.rmi.server.UnicastRemoteObject;
public class HelloClass extends UnicastRemoteObject implements Hello {
public HelloClass() throws Exception{
super();
}
public String Hello(){
return "Hello world!";
}
}
错误信息
Exception in thread "main" java.rmi.ConnectIOException: 在连接创建时出现异常:192.168.2.21;嵌套异常是:
java.net.SocketException: Permission denied: connect
at sun.rmi.transport.tcp.TCPEndpoint.newSocket(TCPEndpoint.java:631)
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.newCall(UnicastRef.java:338)
at sun.rmi.registry.RegistryImpl_Stub.bind(RegistryImpl_Stub.java:60)
at Server.main(Server.java:15)
Caused by: java.net.SocketException: Permission denied: connect
at java.net.DualStackPlainSocketImpl.connect0(Native Method)
at java.net.DualStackPlainSocketImpl.socketConnect(DualStackPlainSocketImpl.java:79)
at java.net.AbstractPlainSocketImpl.doConnect(AbstractPlainSocketImpl.java:350)
at java.net.AbstractPlainSocketImpl.connectToAddress(AbstractPlainSocketImpl.java:206)
at java.net.AbstractPlainSocketImpl.connect(AbstractPlainSocketImpl.java:188)
at java.net.PlainSocketImpl.connect(PlainSocketImpl.java:172)
at java.net.SocksSocketImpl.connect(SocksSocketImpl.java:392)
at java.net.Socket.connect(Socket.java:589)
at java.net.Socket.connect(Socket.java:538)
at java.net.Socket.<init>(Socket.java:434)
at java.net.Socket.<init>(Socket.java:211)
at sun.rmi.transport.proxy.RMIDirectSocketFactory.createSocket(RMIDirectSocketFactory.java:40)
at sun.rmi.transport.proxy.RMIMasterSocketFactory.createSocket(RMIMasterSocketFactory.java:148)
at sun.rmi.transport.tcp.TCPEndpoint.newSocket(TCPEndpoint.java:613)
... 5 more
以上是您提供的内容的翻译。如有需要,还请进一步指示。
英文:
I am trying to get started with java RMI but I keep running in to an error when my components try to bind (or even connect) to the rmiregistry. Whenever I try to bind anything to the rmiregisrty I get a java.rmi.ConnectIOException. I am honestly lost as to what I need to do to fix this.
code
Server
import java.rmi.registry.LocateRegistry;
import java.rmi.registry.Registry;
public class Server {
public static void main(String[] args) throws Exception {
HelloClass Obj = new HelloClass();
Registry registry = LocateRegistry.getRegistry();
registry.bind("Hello", Obj);
System.out.println("Server is live");
}
}
Client
import java.rmi.registry.LocateRegistry;
import java.rmi.registry.Registry;
public class Client {
public static void main(String[] args) throws Exception{
Registry registry = LocateRegistry.getRegistry();
Hello hello = (Hello) registry.lookup("Hello");
String n = hello.Hello();
System.out.println(n);
}
}
Hello (interface)
import java.rmi.*;
public interface Hello extends Remote {
public String Hello() throws RemoteException;
}
HelloClass
import java.rmi.server.UnicastRemoteObject;
public class HelloClass extends UnicastRemoteObject implements Hello {
public HelloClass() throws Exception{
super();
}
public String Hello(){
return "Hello world!";
}
}
The error
"C:\Program Files\Java\jdk1.8.0_144\bin\java.exe" "-javaagent:C:\Program Files\JetBrains\IntelliJ IDEA 2019.3.4\lib\idea_rt.jar=57417:C:\Program Files\JetBrains\IntelliJ IDEA 2019.3.4\bin" -Dfile.encoding=UTF-8 -classpath "C:\Program Files\Java\jdk1.8.0_144\jre\lib\charsets.jar;C:\Program Files\Java\jdk1.8.0_144\jre\lib\deploy.jar;C:\Program Files\Java\jdk1.8.0_144\jre\lib\ext\access-bridge-64.jar;C:\Program Files\Java\jdk1.8.0_144\jre\lib\ext\cldrdata.jar;C:\Program Files\Java\jdk1.8.0_144\jre\lib\ext\dnsns.jar;C:\Program Files\Java\jdk1.8.0_144\jre\lib\ext\jaccess.jar;C:\Program Files\Java\jdk1.8.0_144\jre\lib\ext\jfxrt.jar;C:\Program Files\Java\jdk1.8.0_144\jre\lib\ext\localedata.jar;C:\Program Files\Java\jdk1.8.0_144\jre\lib\ext\nashorn.jar;C:\Program Files\Java\jdk1.8.0_144\jre\lib\ext\sunec.jar;C:\Program Files\Java\jdk1.8.0_144\jre\lib\ext\sunjce_provider.jar;C:\Program Files\Java\jdk1.8.0_144\jre\lib\ext\sunmscapi.jar;C:\Program Files\Java\jdk1.8.0_144\jre\lib\ext\sunpkcs11.jar;C:\Program Files\Java\jdk1.8.0_144\jre\lib\ext\zipfs.jar;C:\Program Files\Java\jdk1.8.0_144\jre\lib\javaws.jar;C:\Program Files\Java\jdk1.8.0_144\jre\lib\jce.jar;C:\Program Files\Java\jdk1.8.0_144\jre\lib\jfr.jar;C:\Program Files\Java\jdk1.8.0_144\jre\lib\jfxswt.jar;C:\Program Files\Java\jdk1.8.0_144\jre\lib\jsse.jar;C:\Program Files\Java\jdk1.8.0_144\jre\lib\management-agent.jar;C:\Program Files\Java\jdk1.8.0_144\jre\lib\plugin.jar;C:\Program Files\Java\jdk1.8.0_144\jre\lib\resources.jar;C:\Program Files\Java\jdk1.8.0_144\jre\lib\rt.jar;C:\Users\Roman\Desktop\RMI3\out\production\RMI3" Server
Exception in thread "main" java.rmi.ConnectIOException: Exception creating connection to: 192.168.2.21; nested exception is:
**"C:\Program Files\Java\jdk1.8.0_144\bin\java.exe" "-javaagent:C:\Program Files\JetBrains\IntelliJ IDEA 2019.3.4\lib\idea_rt.jar=57417:C:\Program Files\JetBrains\IntelliJ IDEA 2019.3.4\bin" -Dfile.encoding=UTF-8 -classpath "C:\Program Files\Java\jdk1.8.0_144\jre\lib\charsets.jar;C:\Program Files\Java\jdk1.8.0_144\jre\lib\deploy.jar;C:\Program Files\Java\jdk1.8.0_144\jre\lib\ext\access-bridge-64.jar;C:\Program Files\Java\jdk1.8.0_144\jre\lib\ext\cldrdata.jar;C:\Program Files\Java\jdk1.8.0_144\jre\lib\ext\dnsns.jar;C:\Program Files\Java\jdk1.8.0_144\jre\lib\ext\jaccess.jar;C:\Program Files\Java\jdk1.8.0_144\jre\lib\ext\jfxrt.jar;C:\Program Files\Java\jdk1.8.0_144\jre\lib\ext\localedata.jar;C:\Program Files\Java\jdk1.8.0_144\jre\lib\ext\nashorn.jar;C:\Program Files\Java\jdk1.8.0_144\jre\lib\ext\sunec.jar;C:\Program Files\Java\jdk1.8.0_144\jre\lib\ext\sunjce_provider.jar;C:\Program Files\Java\jdk1.8.0_144\jre\lib\ext\sunmscapi.jar;C:\Program Files\Java\jdk1.8.0_144\jre\lib\ext\sunpkcs11.jar;C:\Program Files\Java\jdk1.8.0_144\jre\lib\ext\zipfs.jar;C:\Program Files\Java\jdk1.8.0_144\jre\lib\javaws.jar;C:\Program Files\Java\jdk1.8.0_144\jre\lib\jce.jar;C:\Program Files\Java\jdk1.8.0_144\jre\lib\jfr.jar;C:\Program Files\Java\jdk1.8.0_144\jre\lib\jfxswt.jar;C:\Program Files\Java\jdk1.8.0_144\jre\lib\jsse.jar;C:\Program Files\Java\jdk1.8.0_144\jre\lib\management-agent.jar;C:\Program Files\Java\jdk1.8.0_144\jre\lib\plugin.jar;C:\Program Files\Java\jdk1.8.0_144\jre\lib\resources.jar;C:\Program Files\Java\jdk1.8.0_144\jre\lib\rt.jar;C:\Users\Roman\Desktop\RMI3\out\production\RMI3" Server
Exception in thread "main" java.rmi.ConnectIOException: Exception creating connection to: 192.168.2.21; nested exception is:
java.net.SocketException: Permission denied: connect
at sun.rmi.transport.tcp.TCPEndpoint.newSocket(TCPEndpoint.java:631)
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.newCall(UnicastRef.java:338)
at sun.rmi.registry.RegistryImpl_Stub.bind(RegistryImpl_Stub.java:60)
at Server.main(Server.java:15)
Caused by: java.net.SocketException: Permission denied: connect
at java.net.DualStackPlainSocketImpl.connect0(Native Method)
at java.net.DualStackPlainSocketImpl.socketConnect(DualStackPlainSocketImpl.java:79)
at java.net.AbstractPlainSocketImpl.doConnect(AbstractPlainSocketImpl.java:350)
at java.net.AbstractPlainSocketImpl.connectToAddress(AbstractPlainSocketImpl.java:206)
at java.net.AbstractPlainSocketImpl.connect(AbstractPlainSocketImpl.java:188)
at java.net.PlainSocketImpl.connect(PlainSocketImpl.java:172)
at java.net.SocksSocketImpl.connect(SocksSocketImpl.java:392)
at java.net.Socket.connect(Socket.java:589)
at java.net.Socket.connect(Socket.java:538)
at java.net.Socket.<init>(Socket.java:434)
at java.net.Socket.<init>(Socket.java:211)
at sun.rmi.transport.proxy.RMIDirectSocketFactory.createSocket(RMIDirectSocketFactory.java:40)
at sun.rmi.transport.proxy.RMIMasterSocketFactory.createSocket(RMIMasterSocketFactory.java:148)
at sun.rmi.transport.tcp.TCPEndpoint.newSocket(TCPEndpoint.java:613)
... 5 more
**
at sun.rmi.transport.tcp.TCPEndpoint.newSocket(TCPEndpoint.java:631)
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.newCall(UnicastRef.java:338)
at sun.rmi.registry.RegistryImpl_Stub.bind(RegistryImpl_Stub.java:60)
at Server.main(Server.java:15)
Caused by: java.net.SocketException: Permission denied: connect
at java.net.DualStackPlainSocketImpl.connect0(Native Method)
at java.net.DualStackPlainSocketImpl.socketConnect(DualStackPlainSocketImpl.java:79)
at java.net.AbstractPlainSocketImpl.doConnect(AbstractPlainSocketImpl.java:350)
at java.net.AbstractPlainSocketImpl.connectToAddress(AbstractPlainSocketImpl.java:206)
at java.net.AbstractPlainSocketImpl.connect(AbstractPlainSocketImpl.java:188)
at java.net.PlainSocketImpl.connect(PlainSocketImpl.java:172)
at java.net.SocksSocketImpl.connect(SocksSocketImpl.java:392)
at java.net.Socket.connect(Socket.java:589)
at java.net.Socket.connect(Socket.java:538)
at java.net.Socket.<init>(Socket.java:434)
at java.net.Socket.<init>(Socket.java:211)
at sun.rmi.transport.proxy.RMIDirectSocketFactory.createSocket(RMIDirectSocketFactory.java:40)
at sun.rmi.transport.proxy.RMIMasterSocketFactory.createSocket(RMIMasterSocketFactory.java:148)
at sun.rmi.transport.tcp.TCPEndpoint.newSocket(TCPEndpoint.java:613)
... 5 more
答案1
得分: 1
在Server
类中,您通过调用LocateRegistry.getRegistry()
方法检索远程对象注册表引用。
由于未传递主机名和端口,因此内部将使用java.net.InetAddress.getLocalHost().getHostAddress()
API来推导主机名。
根据错误消息,主机名被推导为192.168.2.21,但在该IP上尝试在端口1099上创建套接字时出现了"Permission denied"错误。
您运行Server
类的主机,
该节点是否具有IP地址192.168.2.21?
您可以使用以下命令检查:
ipconfig /all
您还可以使用java.net.InetAddress.getLocalHost().getHostAddress()
API进行检查。
我认为最好您可以尝试将主机名和端口传递给LocateRegistry.getRegistry("127.0.0.1", 1099)
方法。更改需要在Server
和Client
代码中进行。
Server.java
package rmi.learning;
import java.rmi.registry.LocateRegistry;
import java.rmi.registry.Registry;
public class Server {
public static void main(String[] args) throws Exception {
try {
HelloClass Obj = new HelloClass();
Registry registry = LocateRegistry.getRegistry("127.0.0.1", 1099);
System.out.println("registry=" + registry);
registry.bind("Hello", Obj);
System.out.println("Server is live");
} catch (Exception e) {
e.printStackTrace();
}
}
}
Client.java
package rmi.learning;
import java.rmi.registry.LocateRegistry;
import java.rmi.registry.Registry;
public class Client {
public static void main(String[] args) throws Exception {
Registry registry = LocateRegistry.getRegistry("127.0.0.1", 1099);
Hello hello = (Hello) registry.lookup("Hello");
String n = hello.Hello();
System.out.println(n);
}
}
我已将所有类放在rmi.learning
包中。
Hello.java
package rmi.learning;
import java.rmi.Remote;
public interface Hello extends Remote {
String Hello() throws RemoteException;
}
HelloClass.java
package rmi.learning;
import java.rmi.RemoteException;
import java.rmi.server.UnicastRemoteObject;
public class HelloClass extends UnicastRemoteObject implements Hello {
protected HelloClass() throws RemoteException {
super();
}
public String Hello() {
return "Hello world!";
}
}
启动RMI注册表服务:
start d:\Java\jdk1.8.0_261\bin\rmiregistry
从命令提示符执行服务器:
cd d:\workspace_europa\StackOverflow\bin
start /B D:\Java\jdk1.8.0_261\bin\java.exe -classpath .;rmi -Djava.rmi.server.codebase=file:rmi/ rmi.learning.Server
输出:
registry=RegistryImpl_Stub[UnicastRef [liveRef: [endpoint:[127.0.0.1:1099](remote),objID:[0:0:0, 0]]]]
Server is live
从命令提示符执行客户端:
D:\Java\jdk1.8.0_261\bin\java.exe -classpath . rmi.learning.Client
输出:
Hello world!
更多调查:
我尝试复现这个问题,我通过路由器连接到互联网。一旦我连接到WiFi,我的路由器会分配IP地址192.168.0.102。
java.net.InetAddress.getLocalHost().getHostAddress()
API返回的IP地址是192.168.0.102。
无线局域网适配器 Wi-Fi:
连接特定的 DNS 后缀 . . . . . :
链路本地 IPv6 地址 . . . . . : xxxx::xxxx:xxxx:xxxx:xxxx%18
IPv4 地址 . . . . . . . . . . . : 192.168.0.102
子网掩码 . . . . . . . . . . . : 255.255.255.0
默认网关 . . . . . . . . . . . : 192.168.0.1
如果我尝试将RMI服务绑定到IP地址192.168.0.102的端口1099,那么一切正常。
但是,如果我连接到VPN,我的主机会被分配一个新的IP地址。在连接VPN时,IP地址192.168.0.102不再可解析,并且我的机器IP地址会发生变化。这时,如果我尝试将RMI服务绑定到IP地址192.168.0.102,就会出现错误java.net.SocketException: Permission denied: connect.
因此,如果IP地址对当前节点不再适用,就会出现错误。
我在许多地方看到人们建议使用-Djava.net.preferIPv4Stack=true
。在运行Server.class
时,您可以尝试类似的操作:
start /B D:\Java\jdk1.8.0_261\bin\java.exe -Djava.net.preferIPv4Stack=true -classpath .;rmi -Djava.rmi.server.codebase=file:rmi/ rmi.learning.Server
有些地方的人还提到要禁用系统上运行的任何防病毒软件,您可以检查一下这种可能性。
英文:
In Server class you are retrieving remote object registry reference by calling LocateRegistry.getRegistry()
method.
As hostname and port not passed hence internally hostname will be derived using java.net.InetAddress.getLocalHost().getHostAddress()
api.
As per error message hostname is getting derived as 192.168.2.21, but on that IP attempt to create a socket in port 1099 is giving Permission denied error.
The host from where you are running Server class,
Is that node has IP_ADDRESS 192.168.2.21 ?
You may check using
ipconfig /all
You can check using java.net.InetAddress.getLocalHost().getHostAddress()
api.
I think better you may try to pass hostname and port to LocateRegistry.getRegistry("127.0.0.1",1099)
method. Changes are in Server and Client code.
Server.java
package rmi.learning;
import java.rmi.registry.LocateRegistry;
import java.rmi.registry.Registry;
public class Server {
public static void main(String[] args) throws Exception {
try {
HelloClass Obj = new HelloClass();
Registry registry = LocateRegistry.getRegistry("127.0.0.1", 1099);
System.out.println("registry=" + registry);
registry.bind("Hello", Obj);
System.out.println("Server is live");
} catch (Exception e) {
e.printStackTrace();
}
}
}
Client.java
package rmi.learning;
import java.rmi.registry.LocateRegistry;
import java.rmi.registry.Registry;
public class Client {
public static void main(String[] args) throws Exception{
Registry registry = LocateRegistry.getRegistry("127.0.0.1",1099);
Hello hello = (Hello) registry.lookup("Hello");
String n = hello.Hello();
System.out.println(n);
}
}
I have put all classes in rmi.learning package.
Hello.java
package rmi.learning;
import java.rmi.*;
public interface Hello extends Remote {
public String Hello() throws RemoteException;
}
HelloClass.java
package rmi.learning;
import java.rmi.RemoteException;
import java.rmi.server.UnicastRemoteObject;
public class HelloClass extends UnicastRemoteObject implements Hello {
protected HelloClass() throws RemoteException {
super();
}
public String Hello() {
return "Hello world!";
}
}
Start rmi registry service
start d:\Java\jdk1.8.0_261\bin\rmiregistry
From a command prompt:
Execute Server
cd d:\workspace_europa\StackOverflow\bin
start /B D:\Java\jdk1.8.0_261\bin\java.exe -classpath .;rmi -Djava.rmi.server.codebase=file:rmi/ rmi.learning.Server
Output:
registry=RegistryImpl_Stub[UnicastRef [liveRef: [endpoint:[127.0.0.1:1099](remote),objID:[0:0:0, 0]]]]
Server is live
From a command prompt:
Execute Client
D:\Java\jdk1.8.0_261\bin\java.exe -classpath . rmi.learning.Client
Output:
Hello world!
> More investigation:
I was trying to reproduce this issue, I connect to internet via router. Once I connect to wifi then my router is assigning IP address 192.168.0.102.
java.net.InetAddress.getLocalHost().getHostAddress()
api return IP ADDRESS as 192.168.0.102
Wireless LAN adapter Wi-Fi:
Connection-specific DNS Suffix . :
Link-local IPv6 Address . . . . . : xxxx::xxxx:xxxx:xxxx:xxxx%18
IPv4 Address. . . . . . . . . . . : 192.168.0.102
Subnet Mask . . . . . . . . . . . : 255.255.255.0
Default Gateway . . . . . . . . . : 192.168.0.1
If I try to bind rmi service to 192.168.0.102 in port 1099 then it's working fine.
But if I connect to VPN then one new IP is assigned to my host. While connected to VPN, IP 192.168.0.102 is no more resolvable and my machine IP_ADDRESS is getting changed. This time if I try to bind rmi service to IP 192.168.0.102 then getting error java.net.SocketException: Permission denied: connect.
Hence the the error is coming if the IP ADDRESS is not no more applicable for current node.
In many places I have seen people are suggesting to use
-Djava.net.preferIPv4Stack=true also. While running Server.class you may try similar
start /B D:\Java\jdk1.8.0_261\bin\java.exe -Djava.net.preferIPv4Stack=true -classpath .;rmi -Djava.rmi.server.codebase=file:rmi/ rmi.learning.Server
Even some places people are saying about disabling any Anti Virus running on the system, you may check that possibility also.
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论