Something went wrong on our end
-
Brutzman, Don authoredBrutzman, Don authored
MulticastUdpChatKeyboardSender.java 7.56 KiB
package UdpExamples;
import static UdpExamples.MulticastUdpReceiver.BUFFER_LENGTH;
import edu.nps.moves.dis7.utilities.DisThreadedNetworkInterface;
import java.io.*;
import java.net.*;
import java.util.logging.Level;
import java.util.logging.Logger;
/**
* Get keyboard input to send string packets on a UDP multicast group.
* The source looks a lot like MulticastUdpSender.
* TODO: Start this after launching MulticastUdpReceiver.
* 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>.
*
* Privacy note: this sender advertises your user name as part of the multicast packet message
*
* @author mcgredo
* @author brutzman@nps.edu
*/
public class MulticastUdpChatKeyboardSender
{
/** Default constructor */
public MulticastUdpChatKeyboardSender()
{
// default constructor
}
// reserved range for all IPv4 multicast: 224.0.0.0 through 239.255.255.255
// https://www.iana.org/assignments/multicast-addresses/multicast-addresses.xhtml
/** Default multicast group address for send and receive connections.
* @see <a href="https://en.wikipedia.org/wiki/Multicast_address" target="_blank">https://en.wikipedia.org/wiki/Multicast_address</a> */
public static final String MULTICAST_ADDRESS = "239.1.2.15"; // within reserved multicast address range
/** Default socket port used, matches Wireshark DIS capture default
* @see <a href="https://en.wikipedia.org/wiki/Port_(computer_networking)" target="_blank">https://en.wikipedia.org/wiki/Port_(computer_networking)</a> */
public static final int DESTINATION_PORT = 1718;
/** Time to live: how many router-decrement levels can be crossed */
public static final int TTL = 10;
/** How many packets to send prior to termination */
public static final int MAXLOOPSIZE = 100; // or maybe 20000
/** How many packets to send prior to termination */
public static final String LINE_TERMINATOR = "###;"; // do not begin with ;
/** Receiving this message causes termination
* @see <a href="https://en.wikipedia.org/wiki/Sentinel_value" target="_blank">https://en.wikipedia.org/wiki/Sentinel_value</a> */
public static final String QUIT_SENTINEL = "QUIT QUIT QUIT!";
private static NetworkInterface ni;
/**
* Program invocation, execution starts here.
* TODO: allow setting address/port group and provide help message.
* @param args command-line arguments
* @throws java.io.IOException execution error
*/
@SuppressWarnings("SleepWhileInLoop")
public static void main(String[] args) throws IOException
{
MulticastSocket multicastSocket = null;
InetSocketAddress group = null;
// 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);
try
{
System.out.println("UdpExamples.MulticastUdpChatKeyboardSender started...");
// 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 = 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);
group = new InetSocketAddress(multicastAddress, DESTINATION_PORT);
// Join group useful on receiving side
multicastSocket.joinGroup(group, ni = DisThreadedNetworkInterface.findIpv4Interface());
// You can join multiple groups here
byte[] buffer = baos.toByteArray();
DatagramPacket packet = new DatagramPacket(buffer, buffer.length, group/*, DESTINATION_PORT*/);
String userName = System.getProperty("user.name");
String newMessage = new String(); // from user via keyboard
for (int messageIndex = 1; messageIndex < MAXLOOPSIZE; messageIndex++)
{
String spacer = new String(); // align console outputs
if (messageIndex < 10)
spacer = " ";
// Put together an updated packet to send
if (messageIndex < MAXLOOPSIZE)
{
System.out.print ("type new message here: ");
newMessage = System.console().readLine(); // this line blocks, awaiting keyboard input from user
// System.out.println ("[trace] console return: " + newMessage);
// avoid overrunning receive buffer
int maxStringLength = BUFFER_LENGTH - LINE_TERMINATOR.length() - userName.length() - 5;
if (newMessage.length() > maxStringLength)
newMessage = newMessage.substring(0, maxStringLength);
// Put together an updated packet to send
dos.writeChars("[" + userName + " " + spacer + messageIndex + "] ");
dos.writeChars(newMessage + LINE_TERMINATOR); // string chars for readability, include ; semicolon as termination sentinel
}
else dos.writeChars(QUIT_SENTINEL + LINE_TERMINATOR); // note string must include ; semicolon as termination sentinel
buffer = baos.toByteArray();
packet.setData(buffer);
multicastSocket.send(packet);
System.out.print ("Sent packet " + spacer + (messageIndex) + " of " + MAXLOOPSIZE + ": ");
System.out.println("\"" + newMessage + "\"");
baos.reset();
// 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); // only send one per second
}
System.out.println("MulticastSender complete.");
}
catch(IOException | InterruptedException e)
{
System.err.println("Problem with MulticastSender, see exception trace:");
System.err.println(e);
} finally {
if (multicastSocket != null && !multicastSocket.isClosed()) {
try {
multicastSocket.leaveGroup(group, ni);
} catch (IOException ex) {
Logger.getLogger(MulticastUdpChatKeyboardSender.class.getName()).log(Level.SEVERE, null, ex);
}
multicastSocket.close();
}
dos.close();
}
}
}