package UdpExamples; import static UdpExamples.MulticastUdpChatKeyboardSender.LINE_TERMINATOR; import edu.nps.moves.dis7.utilities.DisThreadedNetworkInterface; import java.io.*; import java.net.*; import java.nio.ByteBuffer; import java.util.logging.Level; import java.util.logging.Logger; /** * Send preformatted test packets on a UDP multicast group. * The source looks a lot like UnicastUdpReceiver. Start this before launching MulticastUdpSender. * Multicast must be enabled for the (wired or wireless) LAN that the system is connected too. * Note that these paired programs can communicate within a remote LAN (such as a wireless * home network) even if one or both machines are connected via a * <a href="https://en.wikipedia.org/wiki/Virtual_private_network" target="_blank">Virtual Private Network (VPN)</a>. * * @author mcgredo * @author brutzman@nps.edu */ public class MulticastUdpReceiver { /** Default constructor */ public MulticastUdpReceiver() { // default constructor } // reserved range for all IPv4 multicast: 224.0.0.0 through 239.255.255.255 // https://en.wikipedia.org/wiki/Multicast_address // https://www.iana.org/assignments/multicast-addresses/multicast-addresses.xhtml private static final String MULTICAST_ADDRESS = "239.1.2.15"; private static final int DESTINATION_PORT = 1718; /** * Time to live: how many router-decrement levels can be crossed */ private static final int TTL = 10; private static final boolean INFINITE_READ_LOOP = true; private static NetworkInterface ni; public static final int BUFFER_LENGTH = 1500; /** * Program invocation, execution starts here * @param args command-line arguments */ public static void main(String[] args) { MulticastSocket multicastSocket = null; InetSocketAddress group = null; ByteBuffer buffer = ByteBuffer.allocate(BUFFER_LENGTH); DatagramPacket packet = new DatagramPacket(buffer.array(), buffer.capacity()); try { System.out.println("UdpExamples.MulticastUdpReceiver started..."); // This is a java/IPv6 problem. You should also add it to the // arguments used to start the app, eg -Djava.net.preferIPv4Stack=true // set in the "run" section of preferences. Also, typically // netbeans must be restarted after these settings. // https://stackoverflow.com/questions/18747134/getting-cant-assign-requested-address-java-net-socketexception-using-ehcache System.setProperty("java.net.preferIPv4Stack", "true"); multicastSocket = new MulticastSocket(DESTINATION_PORT); multicastSocket.setTimeToLive(TTL); InetAddress multicastAddress = InetAddress.getByName(MULTICAST_ADDRESS); group = new InetSocketAddress(multicastAddress, DESTINATION_PORT); // Join group useful on receiving side multicastSocket.joinGroup(group, ni = DisThreadedNetworkInterface.findIpv4Interface()); // utility function // You can join multiple groups here System.out.println("Multicast address/port: " + multicastAddress.getHostAddress() + "/" + DESTINATION_PORT + " isBound=" + multicastSocket.isBound()); // unnecessary, no server involved: + "isConnected=" + multicastSocket.isConnected() System.out.println("Multicast packets received log:"); int messageCount = 0; // initialize StringBuilder firstCharacters = new StringBuilder(); char nextChar; while (true) // true is always true, so this is an infinite loop that continues until interrupted { // initializations for this loop int messageIndex = 0; float firstFloat = 0.0f; float secondFloat = 0.0f; multicastSocket.receive(packet); // this method call will block until a packet is received messageCount++; nextChar = ' '; // reinitialize while (nextChar != ';') // read and build string until terminator ; found { nextChar = buffer.getChar(); firstCharacters.append(nextChar); } if (firstCharacters.toString().contains(MulticastUdpSender.QUIT_SENTINEL)) { System.out.println("Received sentinel \"" + MulticastUdpSender.QUIT_SENTINEL + "\""); if (!INFINITE_READ_LOOP) { break; // exit out of reading loop } } boolean foundNumbers = false; String line = firstCharacters.toString(); if (line.contains(LINE_TERMINATOR)) { foundNumbers = false; firstCharacters.setLength(line.length() - LINE_TERMINATOR.length()); // clip EOL sentinel } else if (buffer.hasRemaining()) // likely always true since size is 1500 { messageIndex = buffer.getInt(); firstFloat = buffer.getFloat(); secondFloat = buffer.getFloat(); // simplistic tests for numbers read from buffer if ((messageIndex == 0) && (firstFloat == 0.0f) && (secondFloat == 0.0f)) foundNumbers = false; else if ((messageIndex >= 0) && (messageIndex <= 10000)) foundNumbers = true; } else System.out.print("[trace] no numbers encountered in buffer"); buffer.clear(); if (messageCount < 10) { System.out.print(" "); // prettier output formatting for first nine lines } System.out.println(messageCount + ". \"" + firstCharacters + "\" "); // wrap string in quote marks if (foundNumbers) { System.out.println(" messageIndex=" + messageIndex + ", firstFloat=" + firstFloat + " secondFloat=" + secondFloat); System.out.println(" MulticastUdpReceiver message receipt complete."); } firstCharacters.setLength(0); // reset } } catch (IOException e) { System.err.println("Problem with MulticastUdpReceiver, see exception trace:"); System.err.println(e); } finally // clean up after exit condition { if (multicastSocket != null && !multicastSocket.isClosed()) { try { multicastSocket.leaveGroup(group, ni); } catch (IOException ex) { Logger.getLogger(MulticastUdpReceiver.class.getName()).log(Level.SEVERE, null, ex); } multicastSocket.close(); } // socket/database/completion cleanup code can go here, if needed. System.out.println("MulticastUdpReceiver finally block, complete."); } } }