Java RMI连接使用什么端口?

我可以知道Java RMI连接使用了哪个端口?

如果我想使用RMI连接将Java客户端应用程序连接到Java服务器应用程序,我需要在服务器计算机上打开哪个端口,以便客户端应用程序可以连接到它?

我想在服务器机器中设置防火墙,但我不知道应该打开哪个端口。

RMI通常不能在防火墙上工作,因为它使用不可预测的端口(它从1099开始,然后在随后的端口运行)。

在这些情况下,您通常需要通过HTTP隧道传输RMI,这在此处有详细描述。

在RMI中,关于端口,涉及两种不同的机制:

1)默认情况下,RMI注册表使用端口1099

2)客户端和服务器(存根,远程对象)通过随机端口进行通信,除非在导出远程对象时指定了固定端口。 通信是通过套接字工厂启动的,它使用0作为起始端口,这意味着“使用0到65535之间可用的任何端口”。

到目前为止所有答案都是不正确的。 注册表通常使用端口1099,但您可以更改它。 但这不是故事的结局。 远程对象也使用端口,而不一定是1099。

如果在导出时未指定端口 ,则RMI使用随机端口。 因此解决方案是在导出时指定端口号 。 这是一个需要在防火墙中打开的端口,如果有的话。

  • 在远程对象扩展UnicastRemoteObject的情况下,让其构造函数调用super(port)并使用一些非零端口号。

  • 如果它不扩展UnicastRemoteObject ,请为UnicastRemoteObject.exportObject()提供非零端口号。

这有几个皱纹。

  • 如果您未使用套接字工厂,并且在导出第一个远程对象时提供非零端口号,则RMI将自动与后续导出的远程对象共享该端口,而无需指定端口号或指定零。 第一个远程对象包括使用LocateRegistry.createRegistry().创建的注册表LocateRegistry.createRegistry(). 因此,如果在端口1099上创建Registry ,则从该JVM导出的所有其他对象可以共享端口1099。

  • 如果您正在使用套接字工厂,并且您的RMIServerSocketFactory具有明智的equals() ,则同样适用于上述情况。

  • 在这两种情况下,您可以对所有远程对象使用相同的非零显式端口号,例如createRegistry(1099)后跟任意数量的super(1099)exportObject(..., 1099)调用。

您通常使用rmiregistry命令在服务器上设置端口。 您可以在命令行上设置端口,或者默认为1099

如果您可以修改客户端,那么让它打印出远程引用,您将看到它正在使用的端口。 例如

 ServerApi server = (ServerApi) registry.lookup(ServerApi.RMI_NAME); System.out.println("Got server handle " + server); 

会产生类似的东西:

获得服务器句柄代理[ServerApi,RemoteObjectInvocationHandler [UnicastRef [liveRef:[端点:172.17.3.190:9001,objID:[ – 7c63fea8:…

在那里你可以看到端口是9001.如果远程类没有指定端口,那么它将在重新启动后改变。 如果要使用固定端口,则需要确保远程类构造函数执行以下操作:

 super(rmiPort) 

取决于您如何实现RMI,您可以设置注册表端口(注册表是“唯一的服务点”)。 如果未设置显式端口,则注册表将默认采用端口1099。 在某些情况下,你有一个防火墙,并且防火墙不允许你的rmi-client看到注册表后面的存根和对象,因为这些东西在随机端口运行,注册表使用的是另一个端口,这个端口被防火墙阻止 – 当然。 如果使用RmiServiceExporter配置RmiServer,则可以使用rmiServiceExporter.setServicePort(port)方法修复rmi端口,并在防火墙中打开此端口。

编辑:我用这篇文章解决了这个问题: http : //www.mscharhag.com/java/java-rmi-things-to-remember

参考上面的其他答案,这是我的看法 –

客户端和服务器端都涉及端口。

  • 对于服务器/远程端,如果在不提供端口的情况下导出对象,则远程对象将使用随机端口进行侦听。

  • 一个客户端,当查找远程对象时,它总是使用一个随机端口,并将连接到上面列出的远程对象端口。

端口可在此处获得: java.rmi.registry.Registry.REGISTRY_PORT (1099)

来自java.rmi.registry.Registryjavadoc

因此,注册表的远程对象实现通常使用众所周知的地址导出,例如使用众所周知的ObjID和TCP端口号(默认值为1099 )。

请参阅java.rmi.registry.LocateRegistry的javadoc中的更多内容。