RMI 注册表权限被拒绝

RMI Registry permission denied

我正在尝试开始使用 java RMI,但是当我的组件尝试绑定(甚至连接)到 rmiregistry[时,我一直 运行 出错=31=]。每当我尝试将任何东西绑定到 rmiregisrty 时,我都会得到一个 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("Server is live");
    }
}

客户

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);
    }
}

你好(界面)

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!";
    }

}

错误

"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

在服务器 class 中,您正在通过调用 LocateRegistry.getRegistry() 方法检索远程对象注册表引用。

由于未传递主机名和端口,因此内部主机名将使用 java.net.InetAddress.getLocalHost().getHostAddress() api.

派生

根据错误消息,主机名派生为 192.168.2.21,但在该 IP 上尝试在端口 1099 中创建套接字时出现权限被拒绝错误。

你所在的主机运行服务器class,

那个节点有IP_ADDRESS192.168.2.21吗?

您可以使用

检查
ipconfig /all

您可以使用 java.net.InetAddress.getLocalHost().getHostAddress() api.

检查

我认为您最好尝试将主机名和端口传递给 LocateRegistry.getRegistry("127.0.0.1",1099) 方法。更改在服务器和客户端代码中。

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);
    }
}

我已将所有 class 放入 rmi.learning 包中。

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!";
    }
}

启动 rmi 注册服务

start  d:\Java\jdk1.8.0_261\bin\rmiregistry

从命令提示符: 执行服务器

cd d:\workspace_europa\Whosebug\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!

More investigation:

我试图重现这个问题,我通过路由器连接到互联网。一旦我连接到 wifi,我的路由器就会分配 IP 地址 192.168.0.102。 java.net.InetAddress.getLocalHost().getHostAddress() api return IP 地址为 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
 

如果我尝试将 rmi 服务绑定到端口 1099 中的 192.168.0.102,那么它工作正常。

但是,如果我连接到 VPN,则会为我的主机分配一个新 IP。连接到 VPN 后,IP 192.168.0.102 不再可解析,我的机器 IP_ADDRESS 正在更改。这次如果我尝试将 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

甚至有些地方有人说要在系统上禁用任何防病毒软件 运行,您也可以检查一下这种可能性。