package UdpMulticastHttpExamples;

import java.io.*;
import java.net.*;

/**
 * Looks a lot like UdpSender.  Start this after launching MulticastReceiver.
 * 
 * Privacy note: this sender advertises your user name as part of the multicast packet message
 * 
 * @author mcgredo
 * @author brutzman
 */
public class MulticastSender {

    public static final String MULTICAST_ADDRESS = "239.1.2.15"; // within reserved multicast address range
    public static final int     DESTINATION_PORT = 1718;
    /** Time to live: how many router-decrement levels can be crossed */
    public static final int TTL = 10; 
    
	@SuppressWarnings("SleepWhileInLoop")
    public static void main(String[] args) 
    {
        try
        {
            System.out.println("MulticastSender 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");
            
            // multicast group we are sending to--not a single host
            MulticastSocket multicastSocket = new MulticastSocket(DESTINATION_PORT);
            multicastSocket.setTimeToLive(TTL); // time to live reduces scope of transmission
            InetAddress multicastAddress = InetAddress.getByName(MULTICAST_ADDRESS);
            System.out.println("Multicast address/port: " + multicastAddress.getHostAddress() + "/" + DESTINATION_PORT);
            // Join group useful on receiving side
            multicastSocket.joinGroup(multicastAddress);
            // You can join multiple groups here
            
			int loopSize = 20;
            for (int index = 0; index < loopSize; index++)
            {
            
				// Put together a message with binary content. "ByteArrayOutputStream"
				// is a java.io utility that lets us put together an array of binary
				// data, which we put into the UDP packet.
				ByteArrayOutputStream baos = new ByteArrayOutputStream();
				DataOutputStream       dos = new DataOutputStream(baos);

				// Put together an updated packet to send
				if (index < loopSize - 1)
				{
				// Put together an updated packet to send
					 dos.writeChars(System.getProperty("user.name") + ": ");
					 dos.writeChars("MulticastSender packet " + Integer.toString(index) + ";"); // string chars for readability
					 dos.writeInt  (index); // arbitrary data, needs Java or byte-alignment to read
					 dos.writeFloat(17.0f); // arbitrary data, needs Java or byte-alignment to read
					 dos.writeFloat(23.0f); // arbitrary data, needs Java or byte-alignment to read
				}
				else dos.writeChars("quit;"); // note string must include ; semicolon as termination sentinel
					
				byte[] buffer = baos.toByteArray();
				DatagramPacket packet = new DatagramPacket(buffer, buffer.length, multicastAddress, DESTINATION_PORT);
				
				multicastSocket.send(packet);
				System.out.println("Sent multicast packet " + index + " of " + loopSize);
       
				// How fast does this go? Does UDP try to slow it down, or does
				// this cause network problems? (hint: yes for an unlimited send
				// rate, unlike TCP). How do you know on the receiving side
				// that you haven't received a duplicate UDP packet, out of
				// order packet, or dropped packet?  Necessary considerations.
				Thread.sleep(1000); // Send 100, one per second
            }
            System.out.println("MulticastSender complete.");
        }
        catch(IOException | InterruptedException e)
        {
            System.out.println("Problem with MulticastSender, see exception trace:");
            System.out.println(e);
        }
    }
    
}