Subversion Repositories programming

Rev

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();
    }
}