CodeBlind
CodeBlind

Reputation: 4569

Is there a way to determine if a remote RMI Server machine is multi-homed, even if some of its IP addresses are not visible?

I'm running into a couple of snags getting RMI Servers to work properly on multi-homed machines. I've written a custom RMISocketFactory and I've tried implementing the client-side createSocket(String host, int port) method a couple of different ways. One way only works when the RMI server machine IS multi-homed, the other way only works when the RMI server machine is not. Here is my code for both createSocket method versions in my client-side RMISocketFactory implementation:

Works only when the RMI Server IS NOT Multi-homed:

@Override
public Socket createSocket(String host, int port) throws IOException{
    Socket s = new Socket(host,port);

    //Do some book-keeping here ...

    return s;
}

Works only when the RMI Server IS Multi-homed:

private TreeSet<String> validHosts = null;

@Override
public Socket createSocket(String host, int port) throws IOException{
    Socket s = null;

    try {
        s = new Socket(host,port);
        synchronized(this){
            if(validHosts == null) validHosts = new TreeSet<String>();
            validHosts.add(host);
        }
    } catch (IOException e) {}

    if(s == null && validHosts != null){
        synchronized(this){
            for(String h : validHosts){
                try {
                    s = new Socket(h,port);
                } catch (IOException e) {}
            }
        }
    }

    if(s == null){
        try {
            String h = RemoteServer.getClientHost();
            s = new Socket(RemoteServer.getClientHost(),port);

            synchronized(this){
                if(validHosts == null) validHosts = new TreeSet<String>();
                validHosts.add(h);
            }
        } catch (Exception e) {}
    }

    //No dice - throw an exception:
    if(s == null){
        TreeSet<String> set = new TreeSet<String>();
        set.add(host+"(orig)");

        synchronized(this){
            if(validHosts != null) set.addAll(validHosts);
        }

        StringBuilder sb = new StringBuilder(
            "Could not connect socket on port "+port+
            " to any of the following hosts: ");
        for(String h : set) sb.append(h+" ");

        throw new IOException(sb.toString());
    }

    //Do some book-keeping here ...

    return s;
}

Question

It would seem that if I could somehow tell if the server-side machine was multi-homed, then I could just wrap both sets of code in an if(serverIsMultihomed) ... else ... kind of statement. I do have the ability to get the actual machine name of the server within this call, but calling InetAddress.getAllByHostName(host) doesn't actually return all of the host's IP addresses, only ones that are visible to the NIC on the client's machine. So when createSocket(host,port) gets called with an IP address that isn't actually visible to the client, this is where I run into issues. Furthermore, setting the java.server.rmi.hostname to the IP address of the server that I want to use doesn't fix this problem, and would essentially forbid machines on different subnets that the server is connected to from establishing a link.

The short of it is, is there another way to get all of a host's IP addresses, visible or otherwise, from a different machine, or am I totally barking up the wrong tree here?

Upvotes: 0

Views: 983

Answers (2)

user207421
user207421

Reputation: 310850

If the server has one IP address that's visible to everybody, which seems to be the only multihoming case that Sun considered, all you need to does set java.rmi.server.codebase to that address at the server JVM. No socket factories required at all.

Upvotes: 0

Francis Upton IV
Francis Upton IV

Reputation: 19443

Have you had a look at this Multihomed solution?

Upvotes: 1

Related Questions