在我们的应用程序,我们正在使用马绍尔群岛共和国于客户机-服务器通信在非常不同的方式:

  1. 推动数据从服务的客户得以显示。
  2. 发送控制的信息,从客户向服务器。
  3. 回从那些控制消息的路径代码到达后从服务的客户(栏注意-这是一个副作用的一些遗留系统的代码并不是我们的长期意图).

什么我们要做的就是确保我们的所有马绍尔群岛共和国有关编码将仅使用已知的指定的存货的港口。这包括注册港口(通常预期可1099),服务器的端口和任何口所导致的回调。

这里是我们已经知道的:

  1. LocateRegistry.getRegistry(1099)或者找到。createRegistry(1099)将确保该登记册是在听在1099.
  2. 使用UnicastRemoteObject构造/exportObject静态的方法与一个港口参数将指定服务器的端口。

这些要点还涉及了在这 太阳论坛后.

我们不知道的是:我们如何确保客户连接到服务器所导致的回调只会连接在一指定港口,而不是拖欠到一个匿名的港口?

编辑:增加了一个长长的答复总结了我的调查结果以及我们如何解决这一问题。我们希望,这将有助于其他任何人具有类似问题。

第二编辑:事实证明,在我的应用程序,似乎有一个竞争条件在我的创建和修改的座工厂。我想让用户复盖我的默认设置在一个或平板电脑脚本。可悲的是,它的出现,我的剧本正在运行大大之后的第一座创建的工厂。结果,我得到一个混合的港口从该组默认值和用户设置。更多的工作将是必需的范围这一问题,但我想指出一点兴趣的其他人可能会有可以践踏这些水域在一些。

有帮助吗?

解决方案

你可以这样做一定马绍尔群岛共和国插座工厂。

这座工厂建立的插座马绍尔群岛共和国使用,在客户和服务器的端所以如果你自己写你已经得到了完全控制港口的使用。客户的工厂都建立在服务器,序列化和随后发送给客户,这是相当整洁。

这里有一个导游在阳光告诉你如何做到这一点。

其他提示

你不需要插座工厂,或者甚至多个端口。如果你开始注册服务器JVM可以使用口1099的一切,并事实上那就是将会发生什么,默认。如果你不开始注册,如在客户回调对象,也可以提供口1099时出口。

部分问题有关的客户连接到服务器所导致的回调,'并不是有意义的。他们有不同于原来的客户服务器连接,以及他们将使用同一服务器的端口(s)。

摘要只要回答如下:要解决的问题,我已经(限制服务器和回港口的两端的马绍尔群岛共和国连接),我需要创建两个对客户和服务插座工厂。

再回答随之而来的:

我们的解决将回调的问题已经基本上三个部分。第一是对象包装该需要的能力来指定,这是正在使用一个客户服务器的连接与对于正在使用一个客户服务器回呼。使用的扩展 UnicastRemoteObject 给了我们能够指定的客户和服务插座工厂,我们想到使用。然而,最好的地方锁定在座工厂正在构造的遥对象。

public class RemoteObjectWrapped extends UnicastRemoteObject {
// ....
private RemoteObjectWrapped(final boolean callback) throws RemoteException {
  super((callback ? RemoteConnectionParameters.getCallbackPort() : RemoteConnectionParameters.getServerSidePort()),
        (callback ? CALLBACK_CLIENT_SOCKET_FACTORY : CLIENT_SOCKET_FACTORY),
        (callback ? CALLBACK_SERVER_SOCKET_FACTORY : SERVER_SOCKET_FACTORY));
}
// ....
}

所以,第一个参数的指定部分,其对象是预期的请求,而第二和第三个指定的座工厂,将用于在两端连接的驱动这一远程对象。

因为我们想到限制港口的使用方面,我们需要延长RMI座工厂和锁定的港口。这里有一些草图我们的服务器和客户工厂:

public class SpecifiedServerSocketFactory implements RMIServerSocketFactory {
/** Always use this port when specified. */
private int serverPort;
/**
 * @param ignoredPort This port is ignored.  
 * @return a {@link ServerSocket} if we managed to create one on the correct port.
 * @throws java.io.IOException
 */
@Override
public ServerSocket createServerSocket(final int ignoredPort) throws IOException {
    try {
        final ServerSocket serverSocket = new ServerSocket(this.serverPort);
        return serverSocket;
    } catch (IOException ioe) {
        throw new IOException("Failed to open server socket on port " + serverPort, ioe);
    }
}
// ....
}

注意到,服务器插座工厂上确保只有端口,你以前规定将使用通过该工厂。客户座工厂必须配有适当的座工厂(或者你永远不会连接).

public class SpecifiedClientSocketFactory implements RMIClientSocketFactory, Serializable {
/** Serialization hint */
public static final long serialVersionUID = 1L;
/** This is the remote port to which we will always connect. */
private int remotePort;
/** Storing the host just for reference. */
private String remoteHost = "HOST NOT YET SET";
// ....
/**
 * @param host The host to which we are trying to connect
 * @param ignoredPort This port is ignored.  
 * @return A new Socket if we managed to create one to the host.
 * @throws java.io.IOException
 */
@Override
public Socket createSocket(final String host, final int ignoredPort) throws IOException {
    try {
        final Socket socket = new Socket(host, remotePort);
        this.remoteHost = host;
        return socket;
    } catch (IOException ioe) {
        throw new IOException("Failed to open a socket back to host " + host + " on port " + remotePort, ioe);
    }
}
// ....
}

所以,唯一剩余的力量你的两种方式连接在同一套口是一些逻辑认识到,你打电话回来的客户。在这种情况下,只是确保你的工厂的方法的远程对象调RemoteObjectWrapper构造上的回的参数设置为真实的。

我已经具有各种问题,执行马绍尔群岛共和国服务器和客户的建筑,与客户回调。我的情况是,这两个服务器和客户的背后是防火墙/NAT。最终我得到了一个完整的工作的执行。这里是主要的事情,我没有:

服务器方,当地的IP:192.168.1.10.公共(因特网)IP80.80.80.10

防火墙的路由器/本地服务器的电脑打开口6620.防火墙的路由器/本地服务器的电脑打开口1099.在路由器/NAT重新定向进入的连接在港口6620到192.168.1.10:6620 在路由器/NAT重新定向进入的连接在港口1099到192.168.1.10:1099

在实际的程序:

System.getProperties().put("java.rmi.server.hostname", IP 80.80.80.10);
MyService rmiserver = new MyService();
MyService stub = (MyService) UnicastRemoteObject.exportObject(rmiserver, 6620);
LocateRegistry.createRegistry(1099);
Registry registry = LocateRegistry.getRegistry();
registry.rebind("FAManagerService", stub);

客户方面,当地IP:10.0.1.123公开(因特网)IP70.70.70.20

防火墙的路由器/本地服务器的电脑开放的港口,1999年。在路由器/NAT重新定向进入的连接在港口1999年10.0.1.123:1999年

在实际的程序:

System.getProperties().put("java.rmi.server.hostname", 70.70.70.20);
UnicastRemoteObject.exportObject(this, 1999);
MyService server = (MyService) Naming.lookup("rmi://" + serverIP + "/MyService ");

希望这会有所帮助。奥林匹亚科斯

许可以下: CC-BY-SA归因
不隶属于 StackOverflow
scroll top