简体   繁体   English

Java RMI 连接使用什么端口?

[英]What port is used by Java RMI connection?

May I know what port is used by Java RMI connection?我可以知道 Java RMI 连接使用什么端口吗?

If I want to connect a Java client application to a Java server application using RMI connection, what port I need to open at the server machine so that the client application can connect to it?如果我想使用 RMI 连接将 Java 客户端应用程序连接到 Java 服务器应用程序,我需要在服务器机器上打开什么端口,以便客户端应用程序可以连接到它?

I want to set up a firewall in the server machine but I don't know which port I should open.我想在服务器机器上设置防火墙,但我不知道应该打开哪个端口。

RMI generally won't work over a firewall, since it uses unpredictable ports (it starts off on 1099, and then runs off with a random port after that). RMI 通常不能在防火墙上工作,因为它使用不可预测的端口(它从 1099 开始,然后使用随机端口运行)。

In these situations, you generally need to resort to tunnelling RMI over HTTP, which is described well here .在这些情况下,您通常需要借助 HTTP 上的 RMI 隧道, 此处对此进行了很好的描述。

All the answers so far are incorrect.到目前为止所有的答案都是不正确的。 The Registry normally uses port 1099, but you can change it.注册表通常使用端口 1099,但您可以更改它。 But that's not the end of the story.但这并不是故事的结局。 Remote objects also use ports, and not necessarily 1099.远程对象也使用端口,不一定是 1099。

If you don't specify a port when exporting , RMI uses a random port.如果导出时不指定端口,RMI 使用随机端口。 The solution is therefore to specify a port number when exporting .因此解决方案是在导出时指定端口号 And this is a port that needs opening in the firewall, if any.这是一个需要在防火墙中打开的端口,如果有的话。

  • In the case where your remote object extends UnicastRemoteObject , have its constructor call super(port) with some non-zero port number.在您的远程对象扩展UnicastRemoteObject的情况下,让它的构造函数调用super(port)并带有一些非零端口号。

  • In the case where it doesn't extend UnicastRemoteObject , provide a non-zero port number to UnicastRemoteObject.exportObject() .在它不扩展UnicastRemoteObject的情况下,为UnicastRemoteObject.exportObject()提供一个非零端口号。

There are several wrinkles to this.这有几个皱纹。

  • If you aren't using socket factories, and you provide a non-zero port number when exporting your first remote object, RMI will automatically share that port with subsequently exported remote objects without specified port numbers, or specifying zero. 如果您没有使用套接字工厂,并且在导出第一个远程对象时提供了一个非零端口号,RMI 将自动与随后导出的没有指定端口号或指定为零的远程对象共享该端口。 That first remote object includes a Registry created with LocateRegistry.createRegistry(). 第一个远程对象包括一个用 LocateRegistry.createRegistry().创建的 Registry LocateRegistry.createRegistry(). So if you create a Registry on port 1099, all other objects exported from that JVM can share port 1099. 因此,如果您在端口 1099 上创建 Registry ,则从该 JVM 导出的所有其他对象都可以共享端口 1099。

  • If you are using socket factories, your RMIServerSocketFactory must have a sensible implementation of equals() for port sharing to work, ie one that doesn't just rely on object identity via == or Object.equals() .如果您正在使用套接字工厂,那么您的RMIServerSocketFactory必须有一个合理的equals() RMIServerSocketFactory才能使端口共享工作,即不仅仅依赖于通过==Object.equals()对象标识。

  • If either you don't provide a server socket factory, or you do provide one with a sensible equals() method, but not both, you can use the same non-zero explicit port number for all remote objects, eg createRegistry(1099) followed by any number of super(1099) or exportObject(..., 1099) calls.如果您不提供服务器套接字工厂,或者你提供一个有理智equals()方法,但不能同时,您可以使用相同的非零明确的端口号为所有远程对象,例如createRegistry(1099)后跟任意数量的super(1099)exportObject(..., 1099)调用。

In RMI, with regards to ports there are two distinct mechanisms involved:在 RMI 中,关于端口,涉及两种不同的机制:

  1. By default, the RMI Registry uses port 1099默认情况下,RMI 注册表使用端口 1099

  2. Client and server (stubs, remote objects) communicate over random ports unless a fixed port has been specified when exporting a remote object.除非在导出远程对象时指定了固定端口,否则客户端和服务器(存根、远程对象)通过随机端口进行通信。 The communcation is started via a socket factory which uses 0 as starting port, which means use any port that's available between 1 and 65535.通信是通过套接字工厂启动的,该工厂使用 0 作为起始端口,这意味着使用 1 到 65535 之间可用的任何端口。

You typically set the port at the server using the rmiregistry command.您通常使用 rmiregistry 命令在服务器上设置端口。 You can set the port on the command line, or it will default to 1099可以在命令行设置端口,否则默认为1099

If you can modify the client, then have it print out the remote reference and you will see what port it's using.如果您可以修改客户端,则让它打印出远程引用,您将看到它使用的端口。 Eg例如

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

will produce something like:会产生类似的东西:

Got server handle Proxy[ServerApi,RemoteObjectInvocationHandler[UnicastRef [liveRef: [endpoint:172.17.3.190:9001,objID:[-7c63fea8:...得到服务器句柄 Proxy[ServerApi,RemoteObjectInvocationHandler[UnicastRef [liveRef: [endpoint:172.17.3.190:9001,objID:[-7c63fea8:...]

where you can see the port is 9001. If the remote class is not specifying the port, then it will change across reboots.你可以看到端口是 9001。如果远程类没有指定端口,那么它会在重新启动后发生变化。 If you want to use a fixed port then you need to make sure the remote class constructor does something like:如果要使用固定端口,则需要确保远程类构造函数执行以下操作:

super(rmiPort)

Depends how you implement the RMI, you can set the registry port (registry is a "unique point of services").取决于您如何实现 RMI,您可以设置注册表端口(注册表是“唯一的服务点”)。 If you don't set a explicit port, the registry will assume the port 1099 by default.如果您没有设置显式端口,注册表将默认使用端口 1099。 In some cases, you have a firewall, and the firewall don't allow your rmi-client to see the stubs and objects behind the registry, because this things are running in randomically port, a different port that the registry use, and this port is blocked by firewall - of course.在某些情况下,你有一个防火墙,防火墙不允许你的 rmi 客户端看到注册表后面的存根和对象,因为这些东西在随机端口上运行,注册表使用的不同端口,以及这个端口被防火墙阻止 - 当然。 If you use RmiServiceExporter to configure your RmiServer, you can use the method rmiServiceExporter.setServicePort(port) to fixed the rmi port, and open this port in the firewall.如果您使用RmiServiceExporter来配置您的 RmiServer,您可以使用rmiServiceExporter.setServicePort(port)方法来固定 rmi 端口,并在防火墙中打开该端口。

Edit: I resolve this issue with this post: http://www.mscharhag.com/java/java-rmi-things-to-remember编辑:我用这篇文章解决了这个问题: http : //www.mscharhag.com/java/java-rmi-things-to-remember

From the javadoc of java.rmi.registry.Registry来自java.rmi.registry.Registryjavadoc

Therefore, a registry's remote object implementation is typically exported with a well-known address, such as with a well-known ObjID and TCP port number (default is 1099 ).因此,注册表的远程对象实现通常使用众所周知的地址导出,例如使用众所周知的ObjID和 TCP 端口号(默认为1099 )。

See more in the javadoc of java.rmi.registry.LocateRegistry .java.rmi.registry.LocateRegistryjavadoc 中查看更多信息。

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

With reference to other answers above, here is my view -参考上面的其他答案,这是我的观点 -

there are ports involved on both client and server side.客户端和服务器端都涉及端口。

  • for server/remote side, if you export the object without providing a port , remote object would use a random port to listen.对于服务器/远程端,如果您在不提供端口的情况下导出对象,远程对象将使用随机端口进行侦听。

  • a client, when looks up the remote object, it would always use a random port on its side and will connect to the remote object port as listed above.客户端,在查找远程对象时,它总是在其一侧使用一个随机端口,并将连接到上面列出的远程对象端口。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM