Rev 216 | Go to most recent revision | Blame | Compare with Previous | Last modification | View Log | RSS feed
/*******************************************************************************
* File: P2_Client.java
* Author: Ira W. Snyder (devel@irasnyder.com)
* License: GNU General Public License v2
* Class: CS380 - Computer Networking
*
* Assignment: Project #2
* Date Last Modified: 2006-02-05
*
* Purpose: Implement a simple client allowing the user to send datagrams
* to P2_Server, which will decode them from 4B to 5B encoding. The client
* will retransmit any packets that do not recieve a reply.
******************************************************************************/
import java.io.*;
import java.net.*;
import java.util.*;
public class P2_Client
{
private static int soTimeout = 3000; // 3000 ms timeout = 3 sec
private static DatagramSocket socket;
private static DatagramPacket packet;
private static int portNumber = 1337;
private static int packetNum = 0;
public static boolean verifyInput (String s)
{
int i;
// Check for QUIT message
if (s.equals("QUIT"))
return true;
// If it's not a QUIT, it must be 0's and 1's only
for (i=0; i<s.length; i++)
if (!(s.charAt(i) == '0' || s.charAt(i) == '1'))
return false;
// Everything was a 0 or 1, good!
return true;
}
/**
* Method: readPacket()
* Purpose: Read a packet on the currently opened DatagramSocket,
* and return it as a String.
*/
public static P2_Packet readPacket ()
{
byte[] buf = new byte[256];
packet = new DatagramPacket (buf, buf.length);
try {
socket.receive (packet);
} catch (SocketTimeoutException e) {
System.out.println ("Read timed out, requesting retransmit");
return null;
} catch (PortUnreachableException e) {
System.out.println ("Caught PortUnreachableException, are you" +
" sure the server is running?");
System.exit(1);
} catch (IOException e) {
System.out.println ("Caught exception in readPacket()");
e.printStackTrace();
return null;
}
return new P2_Packet (packet.getData());
}
/**
* Method: writePacket()
* Purpose: Send a packet to localhost:portNumber.
*/
public static boolean writePacket (byte type, byte[] data, int packetNum)
{
InetAddress address = null;
int port = portNumber;
try {
address = InetAddress.getLocalHost();
} catch (UnknownHostException e) {
System.err.println ("Caught UnknownHostException in writePacket(), " +
"are you sure the system is working?");
System.exit(1);
}
byte[] buf = P2_Packet.createPacket (type, data, packetNum);
packet = new DatagramPacket (buf, buf.length, address, port);
try {
socket.send (packet);
} catch (PortUnreachableException e) {
System.out.println ("Caught PortUnreachableException, are " +
"you sure the server is running?");
System.exit(1);
} catch (IOException e) {
System.out.println ("Caught exception in writePacket()");
e.printStackTrace();
return false;
}
return true;
}
/**
* Method: guaranteedTransmit()
* Purpose: A wrapper around readPacket() and writePacket() that implements
* a reliable transmit mechanism.
*/
public static P2_Packet guaranteedTransmit (byte type, byte[] data)
{
P2_Packet reply;
int retries = 0;
writePacket (type, data, packetNum);
reply = readPacket ();
while (reply == null)
{
System.err.println ("Packet lost, retransmitting...");
writePacket (type, data, packetNum);
reply = readPacket ();
retries++;
}
if (retries > 0)
packetNum = 0; //reset packetNum
packetNum++;
return reply;
}
/**
* Method: guaranteedTransmit()
* Purpose: A simplified version of the guaranteedTransmit() above.
*/
public static P2_Packet guaranteedTransmit (byte type)
{
byte[] pData = { 0 };
return guaranteedTransmit (type, pData);
}
/**
* Method: main()
* Purpose: This will accept input from the user, and attempt to send it
* to the corresponding server, which will convert the messages from 4B
* to 5B encoding.
*/
public static void main (String[] args) throws Exception
{
int dropHowMany = 0;
socket = new DatagramSocket();
socket.connect (InetAddress.getLocalHost(), portNumber);
socket.setSoTimeout (soTimeout);
BufferedReader kbd = new BufferedReader (
new InputStreamReader (
System.in));
try {
dropHowMany = Integer.parseInt(args[0]);
} catch (ArrayIndexOutOfBoundsException e) {
System.err.println ("You need to call the program with \'java P2_Client <num>\'");
System.exit(1);
}
String msg;
byte[] pData = { (byte)dropHowMany };
P2_Packet reply = guaranteedTransmit (P2_Packet.DROP, pData);
if (reply.getPacketType() != P2_Packet.DROP)
{
System.err.println ("Unable to inform the server how often to drop packets");
System.exit(1);
}
System.out.print ("% decode: ");
msg = kbd.readLine();
boolean done = false;
while (!done)
{
if (msg.equals("QUIT"))
{
reply = guaranteedTransmit (P2_Packet.QUIT);
done = true;
continue;
}
reply = guaranteedTransmit (P2_Packet.TRANSREQ, P2_EncDec.convertToByteArray(msg));
System.out.println ("-> reply: " + P2_EncDec.convertToString(reply.getPacketData()));
System.out.print ("% decode: ");
msg = kbd.readLine();
}
// Close the socket
socket.close();
}
}