¿Qué puerto usa la conexión Java RMI?

¿Puedo saber qué puerto usa la conexión Java RMI?

Si quiero conectar una aplicación de cliente Java a una aplicación de servidor Java utilizando la conexión RMI, ¿qué puerto necesito abrir en la máquina del servidor para que la aplicación cliente se pueda conectar a él?

Quiero configurar un firewall en la máquina del servidor, pero no sé qué puerto debería abrir.

RMI generalmente no funcionará a través de un firewall, ya que usa puertos impredecibles (comienza en 1099, y luego se ejecuta con un puerto aleatorio después de eso).

En estas situaciones, generalmente debe recurrir a tunneling RMI sobre HTTP, que se describe bien aquí .

En RMI, con respecto a los puertos, hay dos mecanismos distintos involucrados:

1) Por defecto, el registro RMI usa el puerto 1099

2) El cliente y el servidor (stubs, objetos remotos) se comunican a través de puertos aleatorios a menos que se haya especificado un puerto fijo al exportar un objeto remoto. La comunicación se inicia a través de una fábrica de sockets que usa 0 como puerto de inicio, lo que significa “utilizar cualquier puerto que esté disponible” entre 0 y 65535.

Todas las respuestas hasta ahora son incorrectas. El Registro normalmente usa el puerto 1099, pero puede cambiarlo. Pero ese no es el final de la historia. Los objetos remotos también usan puerto, y no necesariamente 1099.

Si no especifica un puerto al exportar , RMI usa un puerto aleatorio. La solución es, por lo tanto, especificar un número de puerto al exportar . Y este es un puerto que necesita abrirse en el firewall, si hay alguno.

  • En el caso en que su objeto remoto amplíe UnicastRemoteObject , UnicastRemoteObject que su constructor llame a super(port) con un número de puerto distinto de cero.

  • En el caso de que no extienda UnicastRemoteObject , proporcione un número de puerto distinto de cero a UnicastRemoteObject.exportObject() .

Hay varias arrugas en esto.

  • Si no está utilizando fábricas de socket y proporciona un número de puerto distinto de cero al exportar su primer objeto remoto, RMI compartirá automáticamente ese puerto con los objetos remotos exportados posteriormente sin los números de puerto especificados, o especificando cero. Ese primer objeto remoto incluye un Registro creado con LocateRegistry.createRegistry(). Por lo tanto, si crea un Registry en el puerto 1099, todos los demás objetos exportados desde esa JVM pueden compartir el puerto 1099.

  • Si está utilizando fábricas de socket y su RMIServerSocketFactory tiene una implementación sensata de equals() , lo mismo se aplica como se RMIServerSocketFactory anteriormente.

  • En ambas condiciones, puede usar el mismo número de puerto explícito distinto de cero para todos los objetos remotos, por ejemplo, createRegistry(1099) seguido de cualquier número de llamadas super(1099) o exportObject(..., 1099) .

Por lo general, configura el puerto en el servidor utilizando el comando rmiregistry. Puede establecer el puerto en la línea de comando, o será predeterminado a 1099

Si puede modificar el cliente, haga que imprima la referencia remota y verá qué puerto está usando. P.ej

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

producirá algo como:

Tengo servidor manejar Proxy [ServerApi, RemoteObjectInvocationHandler [UnicastRef [liveRef: [punto final: 172.17.3.190: 9001, objID: [- 7c63fea8: …

donde puede ver que el puerto es 9001. Si la clase remota no especifica el puerto, cambiará a lo largo de los reinicios. Si desea utilizar un puerto fijo, entonces necesita asegurarse de que el constructor de la clase remota haga algo como:

 super(rmiPort) 

Depende de cómo implemente la RMI, puede configurar el puerto de registro (el registro es un “único punto de servicios”). Si no establece un puerto explícito, el registro asumirá el puerto 1099 de forma predeterminada. En algunos casos, tiene un servidor de seguridad, y el firewall no permite que su cliente rmi vea los stubs y objetos detrás del registro, porque esto se está ejecutando en un puerto aleatorio, un puerto diferente que usa el registro, y este puerto está bloqueado por el firewall, por supuesto. Si usa RmiServiceExporter para configurar su RmiServer, puede usar el método rmiServiceExporter.setServicePort(port) para arreglar el puerto rmi y abrir este puerto en el firewall.

Editar: Resuelvo este problema con esta publicación: http://www.mscharhag.com/java/java-rmi-things-to-remember

Con referencia a otras respuestas anteriores, esta es mi opinión:

hay puertos involucrados tanto en el lado del cliente como del servidor.

  • para servidor / lado remoto, si exporta el objeto sin proporcionar un puerto, el objeto remoto usaría un puerto aleatorio para escuchar.

  • un cliente, cuando busca el objeto remoto, siempre usará un puerto aleatorio de su lado y se conectará al puerto del objeto remoto como se indicó anteriormente.

El puerto está disponible aquí: java.rmi.registry.Registry.REGISTRY_PORT (1099)

Desde el javadoc de java.rmi.registry.Registry

Por lo tanto, la implementación de objetos remotos de un registro normalmente se exporta con una dirección conocida, como con un conocido número de puerto ObjID y TCP (el valor predeterminado es 1099 ).

Vea más en el javadoc de java.rmi.registry.LocateRegistry .