Skip to content
Snippets Groups Projects
Commit b928df61 authored by Brutzman, Don's avatar Brutzman, Don
Browse files

chat client using Java console and keyboard to provide messages to MulticastUdpReceiver

parent 507d6601
No related branches found
No related tags found
No related merge requests found
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();
}
}
}
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment