10 Replies Latest reply: Feb 15, 2007 5:50 PM by 807597 RSS

    Setting network interface and ttl for MulticastSocket

    807597
      Hello

      I've tried to set the network interface and the TTL for a MulticastSocket, but it has no effect. For testing I set the TTL to '4' and the network interface to 'lo' (localhost), but everybody in the local area network get my message with TTL=1...

      I use Fedora Core 5 (Linux), with no settings in the iptables.

      Here is the code I used:

      private String networkInterface="lo";
      private String address="239.192.0.5";
      private int port=54321;
      private int mcastTtl=4;

      public void send(){
      InputStream input=getContextClassLoader().getResourceAsStream("something.xml");
           
      byte[] buffer = new byte[1480];
      int length = input.read(buffer,0, 1480);
           
      inetAddress = InetAddress.getByName(address);
      nInterface=NetworkInterface.getByName(networkInterface);

      MulticastSocket socket = new MulticastSocket(port);
      socket.joinGroup(inetAddress);
      DatagramPacket packet = new DatagramPacket(buffer, length,
      inetAddress, port);
      socket.setTimeToLive(mcastTtl);
      socket.setNetworkInterface(nInterface);
      socket.send(packet);
      socket.leaveGroup(inetAddress);
      }

      For simplicity I took the Error handling off here, but certainly I have it in my code. No errors, no problems, everybody get the correct message... But not with the settings I made.

      Any tips?

      Thanks:
      Bence
        • 1. Re: Setting network interface and ttl for MulticastSocket
          EJP
          Setting the network interface has no effect on sending. It only affects where the joinGroup and leaveGroup messages go. (That also means that you should do it before calling joinGroup or leaveGroup.)

          Multicasts are supposed to go everywhere in the local LAN. They stop at routers which don't have group members behind them.
          • 2. Re: Setting network interface and ttl for MulticastSocket
            807597
            Hello, ejp

            look this link:
            http://java.sun.com/j2se/1.5.0/jcp/rc/apidiffs/java/net/MulticastSocket.html

            it says:
            setNetworkInterface ( NetworkInterface netIf)
            Specify the network interface for outgoing multicast datagrams sent on this socket.

            So this means, that it's for sending multicast datagrams. This is what official documentation says...

            Look, I have a server between two LANs, and I have to send my Datagrams to one of them only.

            ...and additionally this is only the half of the question. What about TTL? Do I have to set this before joining the group too?

            Thanks:
            Bence
            • 3. Re: Setting network interface and ttl for MulticastSocket
              EJP
              My mistake, I should have read my own book. I am wrong and you are correct about setNetworkInterface(), so I don't know why this isn't working.

              However TTL=4 is definitely wrong for what you want. You want TTL=0 for node-local, 1 for link-local, < 32 for site-local, < 64 for region-local < 128 for continent-local, etc. And you only have to set this before sending, as for setNetworkInterface. So TTL=4 is going everywhere in the site, which is what it is specified to do.
              • 4. Re: Setting network interface and ttl for MulticastSocket
                800384
                Wait! ejp is wrong? Oh what a day!
                • 5. Re: Setting network interface and ttl for MulticastSocket
                  EJP
                  Second time this month 99
                  • 6. Re: Setting network interface and ttl for MulticastSocket
                    800369
                    One useful thing to know is that most Linux distributions ship with IPv6 enabled. Java SE detects this and all sockets will be IPv6 sockets. One issue with this is that setting the multicast socket options (like outgoing multicast interface and TTL) just set the options for outgoing IPv6 datagrams - eg: setTimeToLive(4) sets the hop count on out going IPv6 multicast datagrams but IPv4 multicast datagrams continue to use the default (1). There's a bug tracking this although it can't be fixed without using two sockets or else getting the USAGI stack fixed. It's actually debatable if this even if a USAGI issue because the RFCs dealing with IPv4 interoperability do not cover the topic of sending multicast datagrams to IPv4-mapped addresses. If this is the issue you are seeing (assuming you are sending multicasts on the network and not to the loopback) then you can workaround it by running with the java.net.preferIPv4Stack system property set to the value of "true".
                    • 7. Re: Setting network interface and ttl for MulticastSocket
                      807597
                      you mean

                      Properties props=System.getDefaultProperties();
                      props.setProperty("java.net.preferIPv4Stack", "true");

                      I will try

                      Thanks
                      Bence
                      • 8. Re: Setting network interface and ttl for MulticastSocket
                        807597
                        I'm seeing the exact same thing. It's as if setNetworkInterface() doesn't actually do anything at all.

                        java version "1.5.0_09"
                        Java(TM) 2 Runtime Environment, Standard Edition (build 1.5.0_09-b03)
                        Java HotSpot(TM) Server VM (build 1.5.0_09-b03, mixed mode)

                        OS: Linux kernel 2.6.14.3, CentOS 4.2


                        Code example (parts removed for clarity) follows. This code works perfectly when I allow it to attach to the default (eth0) interface. When I try to change the interface it binds to, all packets are still multicast to eth0 ONLY! I see nothing on lo or eth1.


                        Properties props = System.getDefaultProperties();
                        props.setProperty("java.net.preferIPv4Stack","true");

                        MulticastSocket mcs = new MulticastSocket(localPort);
                        mcs.setNetworkInterface(NetworkInterface.getByName("eth1"));

                        InetAddress group = InetAddress.getByName("230.1.1.1");

                        String payload = "This is my payload";
                        DatagramPacket dgram = new DatagramPacket(payload.getBytes(),
                        payload.length(),
                        group, groupPort);
                        mcs.send(dgram);
                        • 9. Re: Setting network interface and ttl for MulticastSocket
                          EJP
                          Not sure what's happening here, but there is some terminological confusion. setNetworkInterface doesn't 'change the interface it binds to', it changes the interface it sends via. The bind address controls what interface is used for receiving and it is usually and by default set to the wildcard address 0.0.0.0, not eth0.

                          Two questions:

                          (a) Are you sure NetworkInterface.getByName("eth1") doesn't return null?

                          (b) can you do route PRINT immediately after this code is run and show the results?
                          • 10. Re: Setting network interface and ttl for MulticastSocket
                            807597
                            We had found this out the hard way as well. If your box is using both stacks and you aren't using IPv6, then u should follow the recommendation made:

                            However, I had to change this code for it to work:
                            Properties props = System.getDefaultProperties();
                            props.setProperty("java.net.preferIPv4Stack","true");
                            to:
                            Properties props = System.getProperties();
                            props.setProperty("java.net.preferIPv4Stack","true");
                            System.setProperties(props);
                            Another note is that you should do this at the entry point of your program before anything else.

                            Otherwise specify it on the command line:
                            java -Djava.net.preferIPv4Stack=true -jar program.jar