Reputation: 4569
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
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