diff --git a/assignments/src/MV3500Cohort2020JulySeptember/homework3/Britt/UdpReceiver.java b/assignments/src/MV3500Cohort2020JulySeptember/homework3/Britt/UdpReceiver.java index e87809cd11168a1121187c3090356ab87c5e1bd5..a5e8ed0506a5d5fc93446965bda84502792d4d23 100644 --- a/assignments/src/MV3500Cohort2020JulySeptember/homework3/Britt/UdpReceiver.java +++ b/assignments/src/MV3500Cohort2020JulySeptember/homework3/Britt/UdpReceiver.java @@ -1,4 +1,4 @@ -package UdpMulticastExamples; +package MV3500Cohort2020JulySeptember.homework3.Britt; import java.io.*; import java.net.*; diff --git a/assignments/src/MV3500Cohort2020JulySeptember/homework3/Britt/UdpSender.java b/assignments/src/MV3500Cohort2020JulySeptember/homework3/Britt/UdpSender.java index a98f5e4ca49bf75a3319ed8c7634ff729fbf23dd..0063106f66a31dfd5bbeea1cd087e7a4bf05da8f 100644 --- a/assignments/src/MV3500Cohort2020JulySeptember/homework3/Britt/UdpSender.java +++ b/assignments/src/MV3500Cohort2020JulySeptember/homework3/Britt/UdpSender.java @@ -1,4 +1,4 @@ -package UdpMulticastExamples; +package MV3500Cohort2020JulySeptember.homework3.Britt; import java.io.*; import java.net.*; diff --git a/assignments/src/MV3500Cohort2020JulySeptember/homework3/Weissenberger/TCPNumberSender.java b/assignments/src/MV3500Cohort2020JulySeptember/homework3/Weissenberger/TCPNumberSender.java index 0301696245af21a2b50b18f3e5d64736a5023a14..44b690d622f7301d32a7627dace377e339ad4f80 100644 --- a/assignments/src/MV3500Cohort2020JulySeptember/homework3/Weissenberger/TCPNumberSender.java +++ b/assignments/src/MV3500Cohort2020JulySeptember/homework3/Weissenberger/TCPNumberSender.java @@ -34,6 +34,11 @@ public class TCPNumberSender { private static final int REPETITION = 1; private static int counter = 0; + /** + * Program invocation, execution starts here + * @param args command-line arguments + * @throws java.lang.InterruptedException user can cancel execution + */ public static void main(String[] args) throws InterruptedException { // Local variables diff --git a/assignments/src/MV3500Cohort2020JulySeptember/homework3/Weissenberger/UDPResultReceiver.java b/assignments/src/MV3500Cohort2020JulySeptember/homework3/Weissenberger/UDPResultReceiver.java index 939f63f4ef32252f4d7a44429938f621c844406e..0a0c4d7525370d5d63489b57b14bb6ef13bd6a3a 100644 --- a/assignments/src/MV3500Cohort2020JulySeptember/homework3/Weissenberger/UDPResultReceiver.java +++ b/assignments/src/MV3500Cohort2020JulySeptember/homework3/Weissenberger/UDPResultReceiver.java @@ -20,10 +20,10 @@ public class UDPResultReceiver { public static final int RECEIVING_PORT = 1415; /** + * Program invocation, execution starts here * @param args command-line arguments - * @throws java.io.IOException */ - public static void main(String[] args) throws IOException + public static void main(String[] args) // throws IOException { DatagramSocket udpSocket = null; diff --git a/assignments/src/MV3500Cohort2020JulySeptember/homework3/WeissenbergerGoericke/TCPNumberSender.java b/assignments/src/MV3500Cohort2020JulySeptember/homework3/WeissenbergerGoericke/TCPNumberSender.java index 77833f77d0807b3a833674750c801b40b08a81b7..e59936ffafb443c9f27ca711ceb62221785eac06 100644 --- a/assignments/src/MV3500Cohort2020JulySeptember/homework3/WeissenbergerGoericke/TCPNumberSender.java +++ b/assignments/src/MV3500Cohort2020JulySeptember/homework3/WeissenbergerGoericke/TCPNumberSender.java @@ -31,8 +31,13 @@ public class TCPNumberSender { public static final int REPETITION = 1; private static int counter = 0; - public static void main(String[] args) throws InterruptedException { - + /** + * Program invocation, execution starts here + * @param args command-line arguments + * @throws java.lang.InterruptedException user can cancel execution + */ + public static void main(String[] args) throws InterruptedException + { // Local variables Socket socket; OutputStream outputStream; diff --git a/assignments/src/MV3500Cohort2020JulySeptember/homework3/WeissenbergerGoericke/UDPResultReceiver.java b/assignments/src/MV3500Cohort2020JulySeptember/homework3/WeissenbergerGoericke/UDPResultReceiver.java index 0aa8262ddc1985e09abc281b44d101bcca527718..45820186eb7f5122c919da79ef58eebb5b5e821a 100644 --- a/assignments/src/MV3500Cohort2020JulySeptember/homework3/WeissenbergerGoericke/UDPResultReceiver.java +++ b/assignments/src/MV3500Cohort2020JulySeptember/homework3/WeissenbergerGoericke/UDPResultReceiver.java @@ -19,10 +19,10 @@ public class UDPResultReceiver { public static final int RECEIVING_PORT = 1415; /** + * Program invocation, execution starts here * @param args command-line arguments - * @throws java.io.IOException */ - public static void main(String[] args) throws IOException + public static void main(String[] args) // throws IOException { DatagramSocket udpSocket = null; diff --git a/assignments/src/MV3500Cohort2020JulySeptember/homework3/White/UdpSender.java b/assignments/src/MV3500Cohort2020JulySeptember/homework3/White/UdpSender.java index f6898e945a92d06f3844cd72f0fb67abedbd7cd4..33b1cc53bddf2e846b07bb4fa295bec2d84a8ea6 100644 --- a/assignments/src/MV3500Cohort2020JulySeptember/homework3/White/UdpSender.java +++ b/assignments/src/MV3500Cohort2020JulySeptember/homework3/White/UdpSender.java @@ -19,10 +19,10 @@ import java.net.*; */ public class UdpSender { - public static final String MY_NAME = "Alex"; // guru incantation 8) -// public static final int SENDING_PORT = 1414; // not needed, can let system choose an open local port - public static final int RECEIVING_PORT = 1415; - public static final int TOTAL_PACKETS_TO_SEND = 100; + private static final String MY_NAME = "Alex"; // guru incantation 8) +// public static final int SENDING_PORT = 1414; // not needed, can let system choose an open local port + public static final int RECEIVING_PORT = 1415; + public static final int TOTAL_PACKETS_TO_SEND = 100; // here is what we need for lab comms public static final String DESTINATION_HOST = "10.1.105.8"; // localhost 127.0.0.1 or argon 10.1.105.1 or 10.1.105.1 or whatever diff --git a/assignments/src/MV3500Cohort2020JulySeptember/homework4/Britt/EspduSender.java b/assignments/src/MV3500Cohort2020JulySeptember/homework4/Britt/EspduSender.java index fe1de553dfd148c75a8e355e80aa8524d33c974d..a8476d7eeae3bcf72095ea92cc6eb2650a98d082 100644 --- a/assignments/src/MV3500Cohort2020JulySeptember/homework4/Britt/EspduSender.java +++ b/assignments/src/MV3500Cohort2020JulySeptember/homework4/Britt/EspduSender.java @@ -1,419 +1,419 @@ -package OpenDis7Examples; - -import java.io.*; -import java.net.*; -import java.util.*; - -import edu.nps.moves.dis7.pdus.*; -import edu.nps.moves.dis7.enumerations.Country; -import edu.nps.moves.dis7.enumerations.EntityKind; -import edu.nps.moves.dis7.enumerations.PlatformDomain; -import edu.nps.moves.dis7.utilities.*; -import edu.nps.moves.dis7.entities.usa.platform.land.M1A2; -import edu.nps.moves.dis7.entities.usa.platform.land.MTVRMK25Cargo; - -/** - * Creates and sends ESPDUs in IEEE binary format. Adapted from OpenDIS library - * example package edu.nps.moves.examples - * - * @author Don McGregor - * @author Don Brutzman - */ -public class EspduSender -{ - /** - * Putting any upper limit on # packets sent avoids possibility of non-terminating infinite loops that continue sending packets. - */ - public static final int NUMBER_OF_LOOPS = 2; // 5 - - /** - * Default multicast group address we send on. - */ - public static final String DEFAULT_MULTICAST_ADDRESS = "239.1.2.3"; - - /** - * Default multicast port used, matches Wireshark DIS capture default - */ - public static final int DEFAULT_MULTICAST_PORT = 3000; - - /** Type of network connection */ - public enum NetworkMode { - /** @see <a href="https://en.wikipedia.org/wiki/Unicast">https://en.wikipedia.org/wiki/Unicast</a> */ - UNICAST, - /** @see <a href="https://en.wikipedia.org/wiki/Multicast">https://en.wikipedia.org/wiki/Multicast</a> */ - MULTICAST, - /** @see <a href="https://en.wikipedia.org/wiki/Broadcasting_(networking)">https://en.wikipedia.org/wiki/Broadcasting_(networking)</a> */ - BROADCAST - }; - - /** - * Output prefix to identify this class, helps with logging - */ - private final static String TRACE_PREFIX = "[" + EspduSender.class.getName() + "] "; - - /** - * Possible system properties, passed in via -Dattr=val networkMode: - * unicast, broadcast, multicast destinationIp: where to send the packet. If - * in multicast mode, this can be multicast. To determine broadcast - * destination IP, use an online broadcast address calculator, for example - * http://www.remotemonitoringsystems.ca/broadcast.php If in multicast mode, - * a join() will be done on the multicast address. port: port used for both - * source and destination. - * - * @param args command-line arguments - */ - @SuppressWarnings("SleepWhileInLoop") // allows Thread.sleep(value) without warning in code - public static void main(String args[]) - { - System.out.println(TRACE_PREFIX + " started..."); - - // Default settings. These are used if no system properties are set. - // If system properties are passed in, these are overridden later. - NetworkMode networkMode = NetworkMode.MULTICAST; - InetAddress address = null; // must be initialized, even if null - int port = DEFAULT_MULTICAST_PORT; - MulticastSocket socket = null; // must be initialized to avoid later error, even if null; - EntityStatePdu espdu = new EntityStatePdu(); - DisTime disTime = new DisTime(); - - // ICBM coordinates for my office - double latitude = 36.639222; - double longitude = -121.803415; - try - { - address = InetAddress.getByName(DEFAULT_MULTICAST_ADDRESS); - } - catch (UnknownHostException e) - { - System.out.println(TRACE_PREFIX + e + " Cannot create multicast address"); - System.exit(0); - } - - // All system properties, passed in on the command line via -Dattribute=value - Properties systemProperties = System.getProperties(); - - // IP address we send to - String destinationIpString = systemProperties.getProperty("destinationIp"); - - // Port we send to, and local port we open the socket on - String portString = systemProperties.getProperty("port"); - - // Network mode: unicast, multicast, broadcast - String networkModeString = systemProperties.getProperty("networkMode"); // unicast or multicast or broadcast - - // Set up socket to send information - try - { - if (portString != null) // Update port we send to, if provided - { - port = Integer.parseInt(portString); - } - socket = new MulticastSocket(port); - - // Where we send packets to, the destination IP address - if (destinationIpString != null) - { - address = InetAddress.getByName(destinationIpString); - } - - // Type of transport: unicast, broadcast, or multicast - if (networkModeString != null) - { - if (networkModeString.equalsIgnoreCase("unicast")) - { - networkMode = NetworkMode.UNICAST; - } - else if (networkModeString.equalsIgnoreCase("broadcast")) - { - networkMode = NetworkMode.BROADCAST; - } - else if (networkModeString.equalsIgnoreCase("multicast")) - { - networkMode = NetworkMode.MULTICAST; - if (!address.isMulticastAddress()) - { - throw new RuntimeException("*** Error: sending to multicast address, but destination address " + address.toString() + "is not multicast"); - } - socket.joinGroup(address); // TODO select correct NetworkInterface - } - } // end networkModeString - else if (networkMode == NetworkMode.MULTICAST) - { - networkModeString = "multicast"; - } - else if (networkMode == NetworkMode.UNICAST) - { - networkModeString = "unicast"; - } - else if (networkMode == NetworkMode.BROADCAST) - { - networkModeString = "broadcast"; - } - } - catch (IOException | RuntimeException e) - { - System.out.println(TRACE_PREFIX + "Unable to initialize network correctly, exiting."); - System.out.println(e); - System.exit(-1); // outta here - } - System.out.println(TRACE_PREFIX + " sending " + networkModeString + " ESPDU packets to " + - address.getHostAddress() + " port " + port); - - // Initialize values in the Entity State PDU object. The exercise ID is - // a way to differentiate between different virtual worlds on one network. - // Note that some values (such as the PDU type and PDU family) are set - // automatically when you create the ESPDU. - espdu.setExerciseID((byte)1); //(short) 1); - - // The EID is the unique identifier for objects in the world. This - // EID should match up with the ID for the object specified in the - // VMRL/x3d/virtual world. - - EntityID entityID = espdu.getEntityID(); // initialize, reset, override - // TODO check: 0 is apparently not a valid site number, per DIS specification - entityID.setSiteID ((short)1); // TODO utility method to allow int values - entityID.setApplicationID((short)2); - entityID.setEntityID ((short)3); - espdu.setEntityID(entityID); // TODO utility method to allow setting all three at once - - // Set the entity type. SISO has a big list of enumerations, so that by - // specifying various numbers we can say this is an M1A2 American tank, - // the USS Enterprise, and so on. We'll make this a tank. There is a - // separate project elsehwhere in this project that implements DIS - // enumerations in C++ and Java, but to keep things simple we just use - // numbers here. - - // Manual way to override platform information: - EntityType entityType = espdu.getEntityType() - .setEntityKind (EntityKind.PLATFORM).setEntityKind (EntityKind.PLATFORM) //(short) 1); // Platform (vs lifeform, munition, sensor, etc.); //(short) 1); // Platform (vs lifeform, munition, sensor, etc.) - .setCountry (Country.UNITED_STATES_OF_AMERICA_USA) // 225 USA - .setDomain (Domain.inst(PlatformDomain.LAND)) // Land (vs air, surface, subsurface, space) - .setCategory ((byte) 7) // Large vic - .setSubCategory((byte) 39) // MTVR - .setSpecific ((byte) 2); // MTVR - - // New way using entity jar(s) - espdu.setEntityType(new edu.nps.moves.dis7.entities.usa.platform.land.MTVRMK25Cargo()); - // or simply use an enumeration by name, with accompanying import statement above - espdu.setEntityType(new MTVRMK25Cargo()); - - // Inspecting an enumeration - System.out.println("==============="); - System.out.println("espdu entityType information:"); - System.out.println(" EntityKind =" + espdu.getEntityType().getEntityKind()); - System.out.println(" Country =" + espdu.getEntityType().getCountry()); - System.out.println(" Domain =" + espdu.getEntityType().getDomain()); - System.out.println(" Category =" + espdu.getEntityType().getCategory()); - System.out.println(" SubCategory=" + espdu.getEntityType().getSubCategory()); - System.out.println(" Specific =" + espdu.getEntityType().getCountry()); - System.out.println("I am an MTVRMK25 Cargo Truck"); - // TODO round trip lookup - - Set<InetAddress> localNetworkAddresses; - - try // Loop through sending N ESPDUs - { - System.out.println(TRACE_PREFIX + "sending " + NUMBER_OF_LOOPS + " sets of packets:"); // + address.toString() - - for (int index = 0; index < NUMBER_OF_LOOPS; index++) - { - // DIS time is a pain in the uh, neck. DIS time units are 2^31-1 units per - // hour, and time is set to DIS time units from the top of the hour. - // This means that if you start sending just before the top of the hour - // the time units can roll over to zero as you are sending. The receivers - // (escpecially homegrown ones) are often not able to detect rollover - // and may start discarding packets as dupes or out of order. We use - // an NPS timestamp here, hundredths of a second since the start of the - // year. The DIS standard for time is often ignored in the wild; I've seen - // people use Unix time (seconds since 1970) and more. Or you can - // just stuff idx into the timestamp field to get something that is monotonically - // increasing. - - // Note that timestamp is used to detect duplicate and out of order packets. - // That means if you DON'T change the timestamp, many implementations will simply - // discard subsequent packets that have an identical timestamp. Also, if they - // receive a PDU with an timestamp lower than the last one they received, they - // may discard it as an earlier, out-of-order PDU. So it is a good idea to - // update the timestamp on ALL packets sent. - // An alterative approach: actually follow the standard. It's a crazy concept, - // but it might just work. - int timestamp = disTime.getDisAbsoluteTimestamp(); - espdu.setTimestamp(timestamp); - - // Set the position of the entity in the world. DIS uses a cartesian - // coordinate system with the origin at the center of the earth, the x - // axis out at the equator and prime meridian, y out at the equator and - // 90 deg east, and z up and out the north pole. To place an object on - // the earth's surface you also need a model for the shape of the earth - // (it's not a sphere.) All the fancy math necessary to do this is in - // the SEDRIS SRM package. There are also some one-off formulas for - // doing conversions from, for example, lat/lon/altitude to DIS coordinates. - // Here we use those one-off formulas. - // Modify the position of the object. This will send the object a little - // due east by adding some to the longitude every iteration. Since we - // are on the Pacific coast, this sends the object east. Assume we are - // at zero altitude. In other worlds you'd use DTED to determine the - // local ground altitude at that lat/lon, or you'd just use ground clamping. - // The x and y values will change, but the z value should not. - //lon = lon + (double)((double)idx / 100000.0); - //System.out.println("lla=" + lat + "," + lon + ", 0.0"); - double direction = Math.pow(-1.0, index); - longitude = longitude + (direction * 0.00006); - - double disCoordinates[] = CoordinateConversions.getXYZfromLatLonDegrees(latitude, longitude, 1.0); - Vector3Double location = espdu.getEntityLocation(); - location.setX(disCoordinates[0]); - location.setY(disCoordinates[1]); - location.setZ(disCoordinates[2]); - System.out.println("==============="); - System.out.println("Create new PDUs"); - System.out.println(" latitude, longitude: [" + latitude + ", " + longitude + "]"); - System.out.println(" coordinate conversion: [" + disCoordinates[0] + ", " + disCoordinates[1] + ", " + disCoordinates[2] + "]"); - - location = espdu.getEntityLocation(); - - System.out.println("Espdu #" + index + " entityID=[" + entityID.getSiteID()+ "," + entityID.getApplicationID()+ "," + entityID.getEntityID()+ "]"); - double c[] = {location.getX(), location.getY(), location.getZ()}; - double lla[] = CoordinateConversions.xyzToLatLonDegrees(c); -// System.out.println(" DIS entityLocation: [" + location.getX() + "," + location.getY() + "," + location.getZ() + "]"); - String debugString = " Location (latitude/longitude/altitude): [" + lla[0] + ", " + lla[1] + ", " + lla[2] + "]"; -// System.out.println(debugString); - - // Optionally, we can do some rotation of the entity - /* - Orientation orientation = espdu.getEntityOrientation(); - float psi = orientation.getPsi(); - psi = psi + idx; - orientation.setPsi(psi); - orientation.setTheta((float)(orientation.getTheta() + idx /2.0)); - */ - // You can set other ESPDU values here, such as the velocity, acceleration, - // and so on. - // Marshal out the espdu object to a byte array, then send a datagram - // packet with that data in it. - - double[] locOr = {location.getX(),location.getY(),location.getZ(), 5,6,1, 1,2,1, 0,0,0, 0,0,0}; - - ByteArrayOutputStream baos = new ByteArrayOutputStream(); - DataOutputStream dos = new DataOutputStream(baos); - DatagramPacket packet; - - // The byte array here is the packet in DIS format. We put that into a - // datagram and send it. - espdu.marshal(dos); - byte[] espduArray = baos.toByteArray(); - - FirePdu firePdu = new FirePdu(); - firePdu.setLocationInWorldCoordinates(espdu.getEntityLocation()); - byte[] fireArray = firePdu.marshal(); - -// CommentPdu newCommentPdu = new CommentPdu(); -// ArrayList<VariableDatum> payloadList = new ArrayList<>(); -// ArrayList<String> commentsList = new ArrayList<>(); -// commentsList.add("Hello CommentPDU"); -// commentsList.add("Here is a second line of text in this comment."); -// if (!commentsList.isEmpty()) -// System.out.println("Preparing CommentPDU:"); -// -// for (String comment : commentsList) -// { -// VariableDatum newVariableDatum = new VariableDatum(); -// newVariableDatum.setVariableDatumValue (comment.getBytes()); // conversion -// newVariableDatum.setVariableDatumLengthInBytes(comment.getBytes().length); // also available in bits, see spec and javadoc -// // alternatively, you do not need to set this and the marshaller will figure it out from the byte array -// // (see javadoc for VariableDatum.setVariableDatumLength()) -// payloadList.add(newVariableDatum); -// System.out.println(" \"" + comment + "\""); -// } -// newCommentPdu.setVariableDatums(payloadList); -// byte[] commentArray = newCommentPdu.marshal(); - - localNetworkAddresses = getBroadcastAddresses(); - for (InetAddress networkAddress : localNetworkAddresses) { - if (espduArray.length > 0) - { - System.out.println(TRACE_PREFIX + "sending datagram packet [" + espdu.getPduType().toString() + "] to " + - String.format("%-15s", networkAddress.getHostAddress()) + " port " + port); - packet = new DatagramPacket(espduArray, espduArray.length, networkAddress, port); - socket.send(packet); - } - // TODO experiment with these! 8) - if (fireArray.length > 0) - { - System.out.println(TRACE_PREFIX + "sending datagram packet [" + firePdu.getPduType().toString() + " ] to " + - String.format("%-15s", networkAddress.getHostAddress()) + " port " + port); - packet = new DatagramPacket(fireArray, fireArray.length, networkAddress, port); // alternate - socket.send(packet); - } -// // TODO experiment with these! 8) -// if (newCommentPdu != null) -// { -// System.out.println(TRACE_PREFIX + "sending datagram packet [" + newCommentPdu.getPduType().toString() + " ] to " + -// String.format("%-15s", networkAddress.getHostAddress()) + " port " + port); -// packet = new DatagramPacket(commentArray, commentArray.length, networkAddress, port); // alternate -// socket.send(packet); -// } - } - // Send every 1 second within loop. Otherwise all this will be all over in a fraction of a second. - Thread.sleep(1000); // msec - } - } - catch (Exception e) - { - System.out.println(TRACE_PREFIX + "Problem with " + e + ", see exception trace:"); - System.out.println(e); - } - System.out.println("==============="); - System.out.println(TRACE_PREFIX + "complete."); - } - - /** - * A number of sites get all snippy about using 255.255.255.255 for a - * broadcast address; it trips their security software and they kick you off - * their network. (Comcast, NPS, etc.) This determines the broadcast address for - * all connected interfaces, based on the IP and subnet mask. If you have a - * dual-homed host it will return a broadcast address for both. If you have - * some VMs running on your host this will pick up the addresses for those - * as well--e.g. running VMWare on your laptop with a local IP this will also - * pick up a 192.168 address assigned to the VM by the host OS. - * - * @return set of all broadcast addresses - */ - public static Set<InetAddress> getBroadcastAddresses() - { - Set<InetAddress> broadcastAddresses = new HashSet<>(); - Enumeration interfaces; - - try { - interfaces = NetworkInterface.getNetworkInterfaces(); - - while (interfaces.hasMoreElements()) - { - NetworkInterface anInterface = (NetworkInterface) interfaces.nextElement(); - - if (anInterface.isUp()) - { - for (InterfaceAddress anAddress : anInterface.getInterfaceAddresses()) { - if ((anAddress == null || anAddress.getAddress().isLinkLocalAddress())) - { - continue; - } - - //System.out.println("Getting broadcast address for " + anAddress); - InetAddress broadcastAddress = anAddress.getBroadcast(); - if (broadcastAddress != null) - { - broadcastAddresses.add(broadcastAddress); - } - } - } - } - } - catch (SocketException e) - { - System.out.println(TRACE_PREFIX + "Problem with .getBroadcastAddresses(), see exception trace:" + e); - System.out.println(e); - } - return broadcastAddresses; - } -} +package MV3500Cohort2020JulySeptember.homework4.Britt; + +import java.io.*; +import java.net.*; +import java.util.*; + +import edu.nps.moves.dis7.pdus.*; +import edu.nps.moves.dis7.enumerations.Country; +import edu.nps.moves.dis7.enumerations.EntityKind; +import edu.nps.moves.dis7.enumerations.PlatformDomain; +import edu.nps.moves.dis7.utilities.*; +import edu.nps.moves.dis7.entities.usa.platform.land.M1A2; +import edu.nps.moves.dis7.entities.usa.platform.land.MTVRMK25Cargo; + +/** + * Creates and sends ESPDUs in IEEE binary format. Adapted from OpenDIS library + * example package edu.nps.moves.examples + * + * @author Don McGregor + * @author Don Brutzman + */ +public class EspduSender +{ + /** + * Putting any upper limit on # packets sent avoids possibility of non-terminating infinite loops that continue sending packets. + */ + public static final int NUMBER_OF_LOOPS = 2; // 5 + + /** + * Default multicast group address we send on. + */ + public static final String DEFAULT_MULTICAST_ADDRESS = "239.1.2.3"; + + /** + * Default multicast port used, matches Wireshark DIS capture default + */ + public static final int DEFAULT_MULTICAST_PORT = 3000; + + /** Type of network connection */ + public enum NetworkMode { + /** @see <a href="https://en.wikipedia.org/wiki/Unicast">https://en.wikipedia.org/wiki/Unicast</a> */ + UNICAST, + /** @see <a href="https://en.wikipedia.org/wiki/Multicast">https://en.wikipedia.org/wiki/Multicast</a> */ + MULTICAST, + /** @see <a href="https://en.wikipedia.org/wiki/Broadcasting_(networking)">https://en.wikipedia.org/wiki/Broadcasting_(networking)</a> */ + BROADCAST + }; + + /** + * Output prefix to identify this class, helps with logging + */ + private final static String TRACE_PREFIX = "[" + EspduSender.class.getName() + "] "; + + /** + * Possible system properties, passed in via -Dattr=val networkMode: + * unicast, broadcast, multicast destinationIp: where to send the packet. If + * in multicast mode, this can be multicast. To determine broadcast + * destination IP, use an online broadcast address calculator, for example + * http://www.remotemonitoringsystems.ca/broadcast.php If in multicast mode, + * a join() will be done on the multicast address. port: port used for both + * source and destination. + * + * @param args command-line arguments + */ + @SuppressWarnings("SleepWhileInLoop") // allows Thread.sleep(value) without warning in code + public static void main(String args[]) + { + System.out.println(TRACE_PREFIX + " started..."); + + // Default settings. These are used if no system properties are set. + // If system properties are passed in, these are overridden later. + NetworkMode networkMode = NetworkMode.MULTICAST; + InetAddress address = null; // must be initialized, even if null + int port = DEFAULT_MULTICAST_PORT; + MulticastSocket socket = null; // must be initialized to avoid later error, even if null; + EntityStatePdu espdu = new EntityStatePdu(); + DisTime disTime = new DisTime(); + + // ICBM coordinates for my office + double latitude = 36.639222; + double longitude = -121.803415; + try + { + address = InetAddress.getByName(DEFAULT_MULTICAST_ADDRESS); + } + catch (UnknownHostException e) + { + System.out.println(TRACE_PREFIX + e + " Cannot create multicast address"); + System.exit(0); + } + + // All system properties, passed in on the command line via -Dattribute=value + Properties systemProperties = System.getProperties(); + + // IP address we send to + String destinationIpString = systemProperties.getProperty("destinationIp"); + + // Port we send to, and local port we open the socket on + String portString = systemProperties.getProperty("port"); + + // Network mode: unicast, multicast, broadcast + String networkModeString = systemProperties.getProperty("networkMode"); // unicast or multicast or broadcast + + // Set up socket to send information + try + { + if (portString != null) // Update port we send to, if provided + { + port = Integer.parseInt(portString); + } + socket = new MulticastSocket(port); + + // Where we send packets to, the destination IP address + if (destinationIpString != null) + { + address = InetAddress.getByName(destinationIpString); + } + + // Type of transport: unicast, broadcast, or multicast + if (networkModeString != null) + { + if (networkModeString.equalsIgnoreCase("unicast")) + { + networkMode = NetworkMode.UNICAST; + } + else if (networkModeString.equalsIgnoreCase("broadcast")) + { + networkMode = NetworkMode.BROADCAST; + } + else if (networkModeString.equalsIgnoreCase("multicast")) + { + networkMode = NetworkMode.MULTICAST; + if (!address.isMulticastAddress()) + { + throw new RuntimeException("*** Error: sending to multicast address, but destination address " + address.toString() + "is not multicast"); + } + socket.joinGroup(address); // TODO select correct NetworkInterface + } + } // end networkModeString + else if (networkMode == NetworkMode.MULTICAST) + { + networkModeString = "multicast"; + } + else if (networkMode == NetworkMode.UNICAST) + { + networkModeString = "unicast"; + } + else if (networkMode == NetworkMode.BROADCAST) + { + networkModeString = "broadcast"; + } + } + catch (IOException | RuntimeException e) + { + System.out.println(TRACE_PREFIX + "Unable to initialize network correctly, exiting."); + System.out.println(e); + System.exit(-1); // outta here + } + System.out.println(TRACE_PREFIX + " sending " + networkModeString + " ESPDU packets to " + + address.getHostAddress() + " port " + port); + + // Initialize values in the Entity State PDU object. The exercise ID is + // a way to differentiate between different virtual worlds on one network. + // Note that some values (such as the PDU type and PDU family) are set + // automatically when you create the ESPDU. + espdu.setExerciseID((byte)1); //(short) 1); + + // The EID is the unique identifier for objects in the world. This + // EID should match up with the ID for the object specified in the + // VMRL/x3d/virtual world. + + EntityID entityID = espdu.getEntityID(); // initialize, reset, override + // TODO check: 0 is apparently not a valid site number, per DIS specification + entityID.setSiteID ((short)1); // TODO utility method to allow int values + entityID.setApplicationID((short)2); + entityID.setEntityID ((short)3); + espdu.setEntityID(entityID); // TODO utility method to allow setting all three at once + + // Set the entity type. SISO has a big list of enumerations, so that by + // specifying various numbers we can say this is an M1A2 American tank, + // the USS Enterprise, and so on. We'll make this a tank. There is a + // separate project elsehwhere in this project that implements DIS + // enumerations in C++ and Java, but to keep things simple we just use + // numbers here. + + // Manual way to override platform information: + EntityType entityType = espdu.getEntityType() + .setEntityKind (EntityKind.PLATFORM).setEntityKind (EntityKind.PLATFORM) //(short) 1); // Platform (vs lifeform, munition, sensor, etc.); //(short) 1); // Platform (vs lifeform, munition, sensor, etc.) + .setCountry (Country.UNITED_STATES_OF_AMERICA_USA) // 225 USA + .setDomain (Domain.inst(PlatformDomain.LAND)) // Land (vs air, surface, subsurface, space) + .setCategory ((byte) 7) // Large vic + .setSubCategory((byte) 39) // MTVR + .setSpecific ((byte) 2); // MTVR + + // New way using entity jar(s) + espdu.setEntityType(new edu.nps.moves.dis7.entities.usa.platform.land.MTVRMK25Cargo()); + // or simply use an enumeration by name, with accompanying import statement above + espdu.setEntityType(new MTVRMK25Cargo()); + + // Inspecting an enumeration + System.out.println("==============="); + System.out.println("espdu entityType information:"); + System.out.println(" EntityKind =" + espdu.getEntityType().getEntityKind()); + System.out.println(" Country =" + espdu.getEntityType().getCountry()); + System.out.println(" Domain =" + espdu.getEntityType().getDomain()); + System.out.println(" Category =" + espdu.getEntityType().getCategory()); + System.out.println(" SubCategory=" + espdu.getEntityType().getSubCategory()); + System.out.println(" Specific =" + espdu.getEntityType().getCountry()); + System.out.println("I am an MTVRMK25 Cargo Truck"); + // TODO round trip lookup + + Set<InetAddress> localNetworkAddresses; + + try // Loop through sending N ESPDUs + { + System.out.println(TRACE_PREFIX + "sending " + NUMBER_OF_LOOPS + " sets of packets:"); // + address.toString() + + for (int index = 0; index < NUMBER_OF_LOOPS; index++) + { + // DIS time is a pain in the uh, neck. DIS time units are 2^31-1 units per + // hour, and time is set to DIS time units from the top of the hour. + // This means that if you start sending just before the top of the hour + // the time units can roll over to zero as you are sending. The receivers + // (escpecially homegrown ones) are often not able to detect rollover + // and may start discarding packets as dupes or out of order. We use + // an NPS timestamp here, hundredths of a second since the start of the + // year. The DIS standard for time is often ignored in the wild; I've seen + // people use Unix time (seconds since 1970) and more. Or you can + // just stuff idx into the timestamp field to get something that is monotonically + // increasing. + + // Note that timestamp is used to detect duplicate and out of order packets. + // That means if you DON'T change the timestamp, many implementations will simply + // discard subsequent packets that have an identical timestamp. Also, if they + // receive a PDU with an timestamp lower than the last one they received, they + // may discard it as an earlier, out-of-order PDU. So it is a good idea to + // update the timestamp on ALL packets sent. + // An alterative approach: actually follow the standard. It's a crazy concept, + // but it might just work. + int timestamp = disTime.getDisAbsoluteTimestamp(); + espdu.setTimestamp(timestamp); + + // Set the position of the entity in the world. DIS uses a cartesian + // coordinate system with the origin at the center of the earth, the x + // axis out at the equator and prime meridian, y out at the equator and + // 90 deg east, and z up and out the north pole. To place an object on + // the earth's surface you also need a model for the shape of the earth + // (it's not a sphere.) All the fancy math necessary to do this is in + // the SEDRIS SRM package. There are also some one-off formulas for + // doing conversions from, for example, lat/lon/altitude to DIS coordinates. + // Here we use those one-off formulas. + // Modify the position of the object. This will send the object a little + // due east by adding some to the longitude every iteration. Since we + // are on the Pacific coast, this sends the object east. Assume we are + // at zero altitude. In other worlds you'd use DTED to determine the + // local ground altitude at that lat/lon, or you'd just use ground clamping. + // The x and y values will change, but the z value should not. + //lon = lon + (double)((double)idx / 100000.0); + //System.out.println("lla=" + lat + "," + lon + ", 0.0"); + double direction = Math.pow(-1.0, index); + longitude = longitude + (direction * 0.00006); + + double disCoordinates[] = CoordinateConversions.getXYZfromLatLonDegrees(latitude, longitude, 1.0); + Vector3Double location = espdu.getEntityLocation(); + location.setX(disCoordinates[0]); + location.setY(disCoordinates[1]); + location.setZ(disCoordinates[2]); + System.out.println("==============="); + System.out.println("Create new PDUs"); + System.out.println(" latitude, longitude: [" + latitude + ", " + longitude + "]"); + System.out.println(" coordinate conversion: [" + disCoordinates[0] + ", " + disCoordinates[1] + ", " + disCoordinates[2] + "]"); + + location = espdu.getEntityLocation(); + + System.out.println("Espdu #" + index + " entityID=[" + entityID.getSiteID()+ "," + entityID.getApplicationID()+ "," + entityID.getEntityID()+ "]"); + double c[] = {location.getX(), location.getY(), location.getZ()}; + double lla[] = CoordinateConversions.xyzToLatLonDegrees(c); +// System.out.println(" DIS entityLocation: [" + location.getX() + "," + location.getY() + "," + location.getZ() + "]"); + String debugString = " Location (latitude/longitude/altitude): [" + lla[0] + ", " + lla[1] + ", " + lla[2] + "]"; +// System.out.println(debugString); + + // Optionally, we can do some rotation of the entity + /* + Orientation orientation = espdu.getEntityOrientation(); + float psi = orientation.getPsi(); + psi = psi + idx; + orientation.setPsi(psi); + orientation.setTheta((float)(orientation.getTheta() + idx /2.0)); + */ + // You can set other ESPDU values here, such as the velocity, acceleration, + // and so on. + // Marshal out the espdu object to a byte array, then send a datagram + // packet with that data in it. + + double[] locOr = {location.getX(),location.getY(),location.getZ(), 5,6,1, 1,2,1, 0,0,0, 0,0,0}; + + ByteArrayOutputStream baos = new ByteArrayOutputStream(); + DataOutputStream dos = new DataOutputStream(baos); + DatagramPacket packet; + + // The byte array here is the packet in DIS format. We put that into a + // datagram and send it. + espdu.marshal(dos); + byte[] espduArray = baos.toByteArray(); + + FirePdu firePdu = new FirePdu(); + firePdu.setLocationInWorldCoordinates(espdu.getEntityLocation()); + byte[] fireArray = firePdu.marshal(); + +// CommentPdu newCommentPdu = new CommentPdu(); +// ArrayList<VariableDatum> payloadList = new ArrayList<>(); +// ArrayList<String> commentsList = new ArrayList<>(); +// commentsList.add("Hello CommentPDU"); +// commentsList.add("Here is a second line of text in this comment."); +// if (!commentsList.isEmpty()) +// System.out.println("Preparing CommentPDU:"); +// +// for (String comment : commentsList) +// { +// VariableDatum newVariableDatum = new VariableDatum(); +// newVariableDatum.setVariableDatumValue (comment.getBytes()); // conversion +// newVariableDatum.setVariableDatumLengthInBytes(comment.getBytes().length); // also available in bits, see spec and javadoc +// // alternatively, you do not need to set this and the marshaller will figure it out from the byte array +// // (see javadoc for VariableDatum.setVariableDatumLength()) +// payloadList.add(newVariableDatum); +// System.out.println(" \"" + comment + "\""); +// } +// newCommentPdu.setVariableDatums(payloadList); +// byte[] commentArray = newCommentPdu.marshal(); + + localNetworkAddresses = getBroadcastAddresses(); + for (InetAddress networkAddress : localNetworkAddresses) { + if (espduArray.length > 0) + { + System.out.println(TRACE_PREFIX + "sending datagram packet [" + espdu.getPduType().toString() + "] to " + + String.format("%-15s", networkAddress.getHostAddress()) + " port " + port); + packet = new DatagramPacket(espduArray, espduArray.length, networkAddress, port); + socket.send(packet); + } + // TODO experiment with these! 8) + if (fireArray.length > 0) + { + System.out.println(TRACE_PREFIX + "sending datagram packet [" + firePdu.getPduType().toString() + " ] to " + + String.format("%-15s", networkAddress.getHostAddress()) + " port " + port); + packet = new DatagramPacket(fireArray, fireArray.length, networkAddress, port); // alternate + socket.send(packet); + } +// // TODO experiment with these! 8) +// if (newCommentPdu != null) +// { +// System.out.println(TRACE_PREFIX + "sending datagram packet [" + newCommentPdu.getPduType().toString() + " ] to " + +// String.format("%-15s", networkAddress.getHostAddress()) + " port " + port); +// packet = new DatagramPacket(commentArray, commentArray.length, networkAddress, port); // alternate +// socket.send(packet); +// } + } + // Send every 1 second within loop. Otherwise all this will be all over in a fraction of a second. + Thread.sleep(1000); // msec + } + } + catch (Exception e) + { + System.out.println(TRACE_PREFIX + "Problem with " + e + ", see exception trace:"); + System.out.println(e); + } + System.out.println("==============="); + System.out.println(TRACE_PREFIX + "complete."); + } + + /** + * A number of sites get all snippy about using 255.255.255.255 for a + * broadcast address; it trips their security software and they kick you off + * their network. (Comcast, NPS, etc.) This determines the broadcast address for + * all connected interfaces, based on the IP and subnet mask. If you have a + * dual-homed host it will return a broadcast address for both. If you have + * some VMs running on your host this will pick up the addresses for those + * as well--e.g. running VMWare on your laptop with a local IP this will also + * pick up a 192.168 address assigned to the VM by the host OS. + * + * @return set of all broadcast addresses + */ + public static Set<InetAddress> getBroadcastAddresses() + { + Set<InetAddress> broadcastAddresses = new HashSet<>(); + Enumeration interfaces; + + try { + interfaces = NetworkInterface.getNetworkInterfaces(); + + while (interfaces.hasMoreElements()) + { + NetworkInterface anInterface = (NetworkInterface) interfaces.nextElement(); + + if (anInterface.isUp()) + { + for (InterfaceAddress anAddress : anInterface.getInterfaceAddresses()) { + if ((anAddress == null || anAddress.getAddress().isLinkLocalAddress())) + { + continue; + } + + //System.out.println("Getting broadcast address for " + anAddress); + InetAddress broadcastAddress = anAddress.getBroadcast(); + if (broadcastAddress != null) + { + broadcastAddresses.add(broadcastAddress); + } + } + } + } + } + catch (SocketException e) + { + System.out.println(TRACE_PREFIX + "Problem with .getBroadcastAddresses(), see exception trace:" + e); + System.out.println(e); + } + return broadcastAddresses; + } +} diff --git a/assignments/src/MV3500Cohort2020JulySeptember/homework4/WeissenbergerGoericke/GermanyEspduVPNReceiver.java b/assignments/src/MV3500Cohort2020JulySeptember/homework4/WeissenbergerGoericke/GermanyEspduVPNReceiver.java index e1dcc49eea24a0812113ede7da3e9dca9b5aa57d..a557c71f53778cd80ca2bceafc432a04d31add64 100755 --- a/assignments/src/MV3500Cohort2020JulySeptember/homework4/WeissenbergerGoericke/GermanyEspduVPNReceiver.java +++ b/assignments/src/MV3500Cohort2020JulySeptember/homework4/WeissenbergerGoericke/GermanyEspduVPNReceiver.java @@ -33,6 +33,10 @@ public class GermanyEspduVPNReceiver { */ private final static String TRACE_PREFIX = "[" + GermanyEspduVPNReceiver.class.getName() + "] "; + /** + * Program invocation, execution starts here + * @param args command-line arguments + */ public static void main(String args[]) { System.out.println(TRACE_PREFIX + "started..."); diff --git a/assignments/src/MV3500Cohort2020JulySeptember/homework4/White/working/PduListenerSaver.java b/assignments/src/MV3500Cohort2020JulySeptember/homework4/White/working/PduListenerSaver.java index e5149fdb471eb39a06a4db3475df5acdffba9787..92dab46cf8511f3133b40e6836e27c6e3f232e13 100644 --- a/assignments/src/MV3500Cohort2020JulySeptember/homework4/White/working/PduListenerSaver.java +++ b/assignments/src/MV3500Cohort2020JulySeptember/homework4/White/working/PduListenerSaver.java @@ -36,7 +36,7 @@ public class PduListenerSaver String multicastAddress = DEFAULT_MULTICAST_ADDRESS; int multicastPort = DEFAULT_MULTICAST_PORT; - System.out.println("OpenDis7Examples.PduListenerSaver started..."); + System.out.println("MV3500Cohort2020JulySeptember.homework4.Britt.PduListenerSaver started..."); switch (args.length) { case 0: diff --git a/assignments/src/MV3500Cohort2021JulySeptember/homework2/HittnerDTcpExample3Client.java b/assignments/src/MV3500Cohort2021JulySeptember/homework2/HittnerDTcpExample3Client.java index 682a2435132c35f7dae16f287136d11bcc9c0a16..8362c3a4632b267e47a6448faadd19c375c619a2 100644 --- a/assignments/src/MV3500Cohort2021JulySeptember/homework2/HittnerDTcpExample3Client.java +++ b/assignments/src/MV3500Cohort2021JulySeptember/homework2/HittnerDTcpExample3Client.java @@ -17,6 +17,7 @@ public class HittnerDTcpExample3Client { /** * Program invocation, execution starts here * @param args command-line arguments + * @throws java.lang.InterruptedException user can cancel execution */ public static void main(String[] args) throws InterruptedException { diff --git a/assignments/src/MV3500Cohort2021JulySeptember/homework2/HittnerNickTcpExample3Client.java b/assignments/src/MV3500Cohort2021JulySeptember/homework2/HittnerNickTcpExample3Client.java index 3b2181ec113de8539797f020909d4fcb12566dc4..a5ef04e793db41b04a9ffcaa0ea6419eb4594292 100644 --- a/assignments/src/MV3500Cohort2021JulySeptember/homework2/HittnerNickTcpExample3Client.java +++ b/assignments/src/MV3500Cohort2021JulySeptember/homework2/HittnerNickTcpExample3Client.java @@ -25,6 +25,7 @@ public class HittnerNickTcpExample3Client { /** * Program invocation, execution starts here * @param args command-line arguments + * @throws java.lang.InterruptedException user can cancel execution */ public static void main(String[] args) throws InterruptedException { diff --git a/assignments/src/MV3500Cohort2021JulySeptember/homework2/Keeven/KeevenTCPExample3Client2.java b/assignments/src/MV3500Cohort2021JulySeptember/homework2/Keeven/KeevenTCPExample3Client2.java index 1881ef609cf00f2ad8939693ccb5fd5aad6bcf7e..f7eb2d3256273c10f286c9e45e98432b2c709fc2 100644 --- a/assignments/src/MV3500Cohort2021JulySeptember/homework2/Keeven/KeevenTCPExample3Client2.java +++ b/assignments/src/MV3500Cohort2021JulySeptember/homework2/Keeven/KeevenTCPExample3Client2.java @@ -1,99 +1,100 @@ -package MV3500Cohort2021JulySeptember.homework2.Keeven; - -import java.io.*; -import java.net.*; - -/** - * This is Assignment 2 where I have modified the given code from TCPExample3Client - * -sleep time has been extended to give more time in between loops - * -Initial print line has been altered to reflect assingnment 2 - * -Loop only runs a finite number of times ,10. - * Before, we always used telnet (netcat) to connect to the server. Here we are - * now writing our own program to do the connection. - * - * As you will see, when we run this after we start the server we will see the - * same string telnet printed, sent by the server. The output at the server will - * show different socket pairs for each time the loop iterates. - * - * @author mcgredo - * @author brutzman - */ -public class KeevenTCPExample3Client2 { - - /** IPv6 String constant for localhost address, similarly IPv4 127.0.0.1 - * @see <a href="https://en.wikipedia.org/wiki/localhost">https://en.wikipedia.org/wiki/localhost</a> - * @see <a href="https://en.wikipedia.org/wiki/IPv6_address">https://en.wikipedia.org/wiki/IPv6_address</a> - */ - public final static String LOCALHOST = "0:0:0:0:0:0:0:1"; - - /** - * Program invocation, execution starts here - * @param args command-line arguments - */ - public static void main(String[] args) throws InterruptedException { - - // Local variables/fields - Socket socket = null; - InputStream is; - Reader isr; - BufferedReader br; - String serverMessage; - int clientLoopCount = 0; - int numbLoops = 10; - - try { - while (clientLoopCount < numbLoops) - { - clientLoopCount++; // increment at beginning of loop for reliability - System.out.println(KeevenTCPExample3Client2.class.getName() + " creating socket..."); - - // We request an IP to connect to ("localhost") and - // port number at that IP (2317). This establishes - // a connection to that IP in the form of a Socket - // object; the server uses a ServerSocket to wait for - // connections. - socket = new Socket(LOCALHOST, 2317); // locohost? - - // Now hook everything up (i.e. set up the streams), Java style: - is = socket.getInputStream(); - isr = new InputStreamReader(is); - br = new BufferedReader(isr); - - // Read a single line written by the server. We'd - // do things a bit differently if there were many lines to be read - // from the server instead of one only. - serverMessage = br.readLine(); - System.out.println("======================Assignment2==========================="); - - System.out.print ("Client loop " + clientLoopCount + ": "); - System.out.println("now we're talking!"); - System.out.println("The message the server sent was: '" + serverMessage + "'"); - // socket gets closed, either automatically/silently by this code (or possibly by the server) - - Thread.sleep(800l); // slow things down, for example 500l (long) = 500 msec - - } // end while(true) // infinite loops are dangerous, be sure to kill this process! - } - catch (IOException e) - { - System.err.println("Problem with " + KeevenTCPExample3Client2.class.getName() + " networking:"); // describe what is happening - System.err.println("Error: " + e); - - // Provide more helpful information to user if exception occurs due to running twice at one time - if (e instanceof java.net.BindException) { - System.err.println("*** Be sure to stop any other running instances of programs using this port!"); - } - } - finally // occurs after any other activity when shutting down - { - try { - if (socket != null) - socket.close(); - } catch (IOException e) {} - - // program exit: tell somebody about that happening. Likely cause: server drops connection. - System.out.println(); - System.out.println(KeevenTCPExample3Client2.class.getName() + " exit"); - } - } -} +package MV3500Cohort2021JulySeptember.homework2.Keeven; + +import java.io.*; +import java.net.*; + +/** + * This is Assignment 2 where I have modified the given code from TCPExample3Client + * -sleep time has been extended to give more time in between loops + * -Initial print line has been altered to reflect assingnment 2 + * -Loop only runs a finite number of times ,10. + * Before, we always used telnet (netcat) to connect to the server. Here we are + * now writing our own program to do the connection. + * + * As you will see, when we run this after we start the server we will see the + * same string telnet printed, sent by the server. The output at the server will + * show different socket pairs for each time the loop iterates. + * + * @author mcgredo + * @author brutzman + */ +public class KeevenTCPExample3Client2 { + + /** IPv6 String constant for localhost address, similarly IPv4 127.0.0.1 + * @see <a href="https://en.wikipedia.org/wiki/localhost">https://en.wikipedia.org/wiki/localhost</a> + * @see <a href="https://en.wikipedia.org/wiki/IPv6_address">https://en.wikipedia.org/wiki/IPv6_address</a> + */ + public final static String LOCALHOST = "0:0:0:0:0:0:0:1"; + + /** + * Program invocation, execution starts here + * @param args command-line arguments + * @throws java.lang.InterruptedException user can cancel execution + */ + public static void main(String[] args) throws InterruptedException { + + // Local variables/fields + Socket socket = null; + InputStream is; + Reader isr; + BufferedReader br; + String serverMessage; + int clientLoopCount = 0; + int numbLoops = 10; + + try { + while (clientLoopCount < numbLoops) + { + clientLoopCount++; // increment at beginning of loop for reliability + System.out.println(KeevenTCPExample3Client2.class.getName() + " creating socket..."); + + // We request an IP to connect to ("localhost") and + // port number at that IP (2317). This establishes + // a connection to that IP in the form of a Socket + // object; the server uses a ServerSocket to wait for + // connections. + socket = new Socket(LOCALHOST, 2317); // locohost? + + // Now hook everything up (i.e. set up the streams), Java style: + is = socket.getInputStream(); + isr = new InputStreamReader(is); + br = new BufferedReader(isr); + + // Read a single line written by the server. We'd + // do things a bit differently if there were many lines to be read + // from the server instead of one only. + serverMessage = br.readLine(); + System.out.println("======================Assignment2==========================="); + + System.out.print ("Client loop " + clientLoopCount + ": "); + System.out.println("now we're talking!"); + System.out.println("The message the server sent was: '" + serverMessage + "'"); + // socket gets closed, either automatically/silently by this code (or possibly by the server) + + Thread.sleep(800l); // slow things down, for example 500l (long) = 500 msec + + } // end while(true) // infinite loops are dangerous, be sure to kill this process! + } + catch (IOException e) + { + System.err.println("Problem with " + KeevenTCPExample3Client2.class.getName() + " networking:"); // describe what is happening + System.err.println("Error: " + e); + + // Provide more helpful information to user if exception occurs due to running twice at one time + if (e instanceof java.net.BindException) { + System.err.println("*** Be sure to stop any other running instances of programs using this port!"); + } + } + finally // occurs after any other activity when shutting down + { + try { + if (socket != null) + socket.close(); + } catch (IOException e) {} + + // program exit: tell somebody about that happening. Likely cause: server drops connection. + System.out.println(); + System.out.println(KeevenTCPExample3Client2.class.getName() + " exit"); + } + } +} diff --git a/assignments/src/MV3500Cohort2021JulySeptember/homework2/Schlessel/SchlesselClient.java b/assignments/src/MV3500Cohort2021JulySeptember/homework2/Schlessel/SchlesselClient.java index 159f30080e2d2bc4554252368ee69308bd411e53..a4dfad9f5e10c36a261eca54290b7d687bf83ee3 100644 --- a/assignments/src/MV3500Cohort2021JulySeptember/homework2/Schlessel/SchlesselClient.java +++ b/assignments/src/MV3500Cohort2021JulySeptember/homework2/Schlessel/SchlesselClient.java @@ -17,6 +17,7 @@ public class SchlesselClient { /** * Program invocation, execution starts here * @param args command-line arguments + * @throws java.lang.InterruptedException user can cancel execution */ public static void main(String[] args) throws InterruptedException {