views:

235

answers:

4

I have a Java application that registers a server component in a service provider, and then sends the service name to a client. The client uses the service name to get an address out of the service provider to the server. However, the server has several interfaces only 1 of which the client get get at, so the service must be registered with the right IP. We discovered the client through a broadcast, so I have the client IP and an Enumeration of the computers network interfaces. How do I match the IP to an interface, not knowing what the netmask of the client IP is?

Spontaneously I imagine turning all the addresses to ints and chomping the local ips with their netmask and looking for a 'best match', but I wonder if there is a better way?

(this is an enterprise(tm) solution, so cutting out the service provider isn't an option, at least not w/o a political campaign first ;) )

A: 

This depends on how you are going about this.

Sample code much?

There is a a ".getHostAddress()" method for InetAddress which might be useful.

narkie1987
Currently I just grab NetworkInterface.getNetworkInterfaces, go through them all, look at all their inetAddresses (yes, with getHostAddress) and then match the first 3 octets. But like I said, I can't assume a 255.255.255.0 bitmask (or any other) so I'm looking for a more robust solution. Sort of a combination of isReachable and getByAddress would have been nice, but I've not found anything like that in the API.
Per Fagrell
"Sort of a combination of isReachable and getByAddress would have been nice, but I've not found anything like that in the API." - You already have the addresses and InetAdress has a method isReachable(int timeout) (since 1.5), although according to the docs "A typical implementation will use ICMP ECHO REQUESTs if the privilege can be obtained, otherwise it will try to establish a TCP connection on port 7 (Echo) of the destination host. " so that would need to be enabled on the service machine.
M. Jessup
A: 

This is usually done using DNS. The interface should be listed in DNS so you can reach it by name rather than address servicehost.example.com rather than 192.0.2.42.

BillThor
That's true. I'm not sure if there's any dns server set up in this environment, and the service provider only takes a straight IP right now (and is owned by a department in another country). But if I could use DNS, I'd still need to register a separate name for each address wouldn't I? I'd need to know which name was reachable from the given IP, and I'd be in more or less the same situation. Or do DNS servers handle this intrinsically?
Per Fagrell
A: 

It is more a network administration issue than the application.

Consider the server (hosting the java application) is multi-homed. it can be three address: 1. 99.88.77.66 (Public IP) 2. 10.10.10.10 (Private, Internally assigned IP)

Which IP will your potential client can get access depends on the network configuration.

The client may access from a public IP, but it will access your private IP due to NAT. Another example, may be your client IP is 192.168.10.10, through NAT, it access your 10.10.10.10 IP.

You cannot calculated the correct IP (to publish your service) by any kind of prefix matching.

You have mentioned that, it is an enterprise solution, and complex network configuration is common in such kind of environment.

With DNS, your server host may be myapp.company.com It is is up to the DNS facility to resolve the correct IP for the client. You may need to get coordinate with networking guy, with proper support in DNS, the solution should be trivial and more robust.

Zarick Lau
+1  A: 

By my understanding, the service provider has interfaces on multiple distinct networks. Each client is on only one of those networks and thus can only communicate with one of the interfaces. The service needs to discover which of the interfaces is accessible to the client so that it may send the correct address. You (the service developer) have no control over the network environment into which the service is deployed and thus cannot employ network-level solutions such as DNS.

In many network setups routing is symmetric. That is, the route from host A to host B is the same as that from host B to host A. If you know this to be the case in all environments to which your service will be deployed then you can safely assume that the address used to connect to the client is accessible to the client. That address could be discovered, for example, by connecting a DatagramSocket to the client and then calling its getLocalAddress() method.

If routing is asymmetric I know of no way to determine whether a particular interface is accessible to the client using only the java.net API. If you control the client implementation you might be able to have it include the broadcast source address (which should be the server interface visible to it) in its broadcast response packet. Beyond that, you haven't included enough information about the scenario to give specific advice. For example, it would be useful to know what protocol is used for the broadcast advertisement and client response thereto.

Sam Hanes
The underlying OS should take care of most of the low level socket stuff. Just create the socket and call the get local address method. As a last resort, with the enumeration of local addresses you have go through and create sockets, bind each them to a socket, and see if you can connect to your client. But `Socket(clientIP,port).getLocalAddress()` should work.
Allen
That should work so long as routing on the network is symmetric. If it's not the local IP used to send datagrams to the client may not be the same as the one the client has access to.
Sam Hanes