views:

250

answers:

4

In my program I'm sending out UDP broadcasts and reacting to them. I need a way to ignore the UDP broadcasts that I send out, but react to ones that aren't from my machine.

I did try using: if (NetworkInterface.getByInetAddress(packet.getAddress()) != null) but this generated IOExceptions in some cases (java.net.SocketException: no network interface is bound to such an IP address)

Anyone any ideas?

Also: getInetAddress() on my socket throws a NullPointerException

+1  A: 

Can't you just do an equals() between packet.getAddress() an an Address object for your own host?

Carl Smotricz
The `DatagramSocket` is bound to 0.0.0.0 but the packet originates from a LAN IP (192.168.1.103 in this case) - that's why I was trying to see if the packet's source address was in `NetworkInterface.getByInetAddres()`
amr
Bummer! I've also had a hard time getting a meaningful address for my own host. How about sending yourself a test message at initialization time? Sounds kludgy but I'm almost out of ideas.
Carl Smotricz
+1  A: 

This is not exactly an answer to your question. But for handling UDP broadcasts you should have a look at JGroups:

JGroups is a toolkit for reliable multicast communication. (Note that this doesn't necessarily mean IP Multicast, JGroups can also use transports such as TCP). It can be used to create groups of processes whose members can send messages to each other. The main features include

  • Group creation and deletion. Group members can be spread across LANs or WANs
  • Joining and leaving of groups
  • Membership detection and notification about joined/left/crashed members
  • Detection and removal of crashed members
  • Sending and receiving of member-to-group messages (point-to-multipoint)
  • Sending and receiving of member-to-member messages (point-to-point)
tangens
+1  A: 

I think there's a little discrepancy between the javadoc and the actual implementation of NetworkInterface getByInetAddress(). The javadoc seems to suggest that getByInetAddress would return null if no match was found, yet the implementation either returns a match, either throws a SocketException.

JavaDoc

public static NetworkInterface getByInetAddress(InetAddress addr)
                                               throws SocketException

Returns: A NetworkInterface or null if there is no network interface with the specified IP address.

Implementation

  public static NetworkInterface getByInetAddress (InetAddress addr)
    throws SocketException
  {
    if (networkInterfaces == null)
      networkInterfaces = getRealNetworkInterfaces ();

    for (Enumeration interfaces = networkInterfaces.elements ();
         interfaces.hasMoreElements (); )
      {
        NetworkInterface tmp = (NetworkInterface) interfaces.nextElement ();

        for (Enumeration addresses = tmp.inetAddresses.elements ();
             addresses.hasMoreElements (); )
          {
            if (addr.equals ((InetAddress) addresses.nextElement ()))
              return tmp;
          }
      }

    throw new SocketException (
      "no network interface is bound to such an IP address");
  }

I suggest to either catch the exception and treat it as an answer from a 3rd party, either re-implement it using the getNetworkInterfaces() method.

Yannick M.
Ah, that makes more sense, thanks.I'm only really interested in when the broadcast isn't from my machine, so I'm not sure catching it is my best option.Would it be silly to just reimplement getByInetAddress as a method in my class and have it not throw an exception?
amr
I'm all for improving readability, so reimplementing might be the better option.
Yannick M.
+3  A: 

The "industrial strength" solution to this, of course, would be to generate yourself a random UUID for each server, and to include this ID (it could be an int or maybe a long) in each packet. If that ID matches your own, you can drop it.

I'm not enamored of this solution because it wastes a number of bytes in each datagram packet. But it's simple and effective.

Carl Smotricz