/* * Copyright (c) 2001 Matthew Feldt. All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided the copyright notice above is * retained. * * THIS SOFTWARE IS PROVIDED ''AS IS'' AND WITHOUT ANY EXPRESSED OR * IMPLIED WARRANTIES. */ /** * UDPSend.java * * Java Examples In A Nutshell Copyright (c) 2000 David Flanagan * Exercise 5-6: * Modify the UDPSend and UDPReceive programs of Example 5-11 and Example * 5-12 so that UDPReceive sends an acknowledgement when it receives a data- * gram, and so that UDPSend doesn't exit until it receives the acknowledgement. * The acknowledgement should itself be a datagram and can contain any data * you desire. (You could use the checksum classes of the java.util.zip pack- * age, for example, to compute a checksum of the received data and send this * back in the acknowledgement packet.) Use the setSoTimeout() method of * DatagramSocket so that UDPSend doesn't wait for more than a few seconds to * receive the acknowledgment. If the acknowledgment packet is not received * before the timeout, UDPSend should assume that the original packet got lost * and was not received. Your modified UDPSend should try to resend the packet * once or twice , and if it still doesn't receive an acknowledgment, it should * exit with an error message. * * @author Matthew Feldt * @version 1.0, 03/08/2001 13:41 */ package com.feldt.examples.net; import java.io.*; import java.net.*; import java.util.zip.*; class UDPSendPacket extends Thread { private InetAddress address; private int port; private byte[] message; UDPSendPacket(InetAddress a, int p, byte[] m) { address = a; port = p; message = m; } public void run() { try { DatagramPacket packet = new DatagramPacket(message, message.length, address, port); // calculate the message crc checksum and print intentions... CRC32 crc = new CRC32(); crc.update(message); System.out.println("Sending"); System.out.println(" message : " + new String(message)); System.out.println(" crc : " + crc.getValue()); System.out.println(" to : " + address.getHostName() + ":" + packet.getPort()); // create datagram socket, send packet through it, close it. DatagramSocket dsocket = new DatagramSocket(); dsocket.send(packet); dsocket.close(); } catch (Exception e) { System.err.println("UDPSendPacket.run():" + e.getMessage()); } } } public class UDPSend { static final String USAGE = "Usage: java UDPSend ...\n" + " or: java UDPSend -f "; static final int ACK_PORT = 9999; static final int RETRY_LIMIT = 3; static final int BUFFER_SIZE = 2048; public static void main(String args[]) { InetAddress address; int port, retryCount = 0; byte[] message; try { if (args.length < 3) // must have at least three arguments throw new IllegalArgumentException("wrong number of args"); // parse the arguments address = InetAddress.getByName(args[0]); port = Integer.parseInt(args[1]); // determine what to send. if args[2] equals "-f" then args[3] // will contain a filename, otherwise concatenate remaining // arguments in to byte[] message if (args[2].equals("-f")) { if (args.length != 4) throw new IllegalArgumentException("wrong number of args"); File f = new File(args[3]); int len = (int)f.length(); // determine file size message = new byte[len]; // create a file size buffer FileInputStream in = new FileInputStream(f); int bytes_read = 0, n; do { // read the entire file n = in.read(message, bytes_read, len-bytes_read); bytes_read += n; } while((bytes_read < len) && (n != -1)); } else { // otherwise concatenate remaining arguments String msg = args[2]; for (int i = 3; i < args.length; i++) msg += " " + args[i]; message = msg.getBytes(); } byte[] ack = new byte[BUFFER_SIZE]; DatagramPacket ackPacket = new DatagramPacket(ack, ack.length); DatagramSocket ackSocket = new DatagramSocket(ACK_PORT); for (;;) { // set acknowledgment delay tollerance (in milliseconds) ackSocket.setSoTimeout(1000); // create a seperate thread to send datagram UDPSendPacket udpSend = new UDPSendPacket(address, port, message); udpSend.start(); try { ackSocket.receive(ackPacket); // wait for acknowledgment // print status String ackString = new String(ack, 0, ackPacket.getLength()); System.out.println("Acknowledgment"); System.out.println(" message : " + ackString); break; } catch (InterruptedIOException e) { // acknowledgment timeout if (++retryCount >= RETRY_LIMIT) { // exceeded retry limit System.err.println("Max retry limit reached."); System.exit(-1); } System.err.println("** " + e.getMessage() + " **"); } } } catch (Exception e) { System.err.println(e.getMessage()); System.err.println(USAGE); } } }