Title: Networking part 2
Course: CPS 261: Advanced Java Concepts ~ DL & MM MASTER

Networking part 2

Reading and Writing Serialized Objects across Sockets

Suppose that you need to pass more sophisticated objects than strings across the network. After all you are creating a game that has lots of different data types. You could figure out a way to convert your complicated game structure into a series of strings and then convert the strings back to your game structure. But this is a lot of work. Especially if someone tells you that Java can automically figure out how to pass a class across the network.

So lets rework the above EchoServer/Client to pass a class across the network instead of a string. I have highlighted the key Java tricks to make this class transferable across the network. Suppose that the class we want to pass across looks like the following:


import java.io.Serializable;
import java.util.Date;
import java.util.ArrayList;

// A serializable class that can be easily read and written
// to a socket.  Note that all of your classes must implement
// Serializable.  If you include some one elses class, make
// sure they too implement Serializable.  Note that most
// Java classes (like String, Date, ArrayList, etc.) do
// implement Serializable

public class UserInputs implements Serializable
{
    int counter=0;
    String lastMessage; // already serializable
    ArrayList<Data> list = new ArrayList<Data>(); // already serializable

// endOfLine will be '\r\n' on Windows and '\n' on Linux
    String endOfLine = System.getProperty("line.separator");

// BEGIN INNER CLASS
    class Data implements Serializable

    {
        Date date; // already serializable
        String str;
        Data(String s)
        {
            date = new Date();
            str =s;
        }

// toString makes it easy to create output of this class
        public String toString()
        {
            return date +" " + str;
        }
    }
 // END INNER CLASS

    void addMsg(String s)
    {
        list.add( new Data(s));
        counter += 1;
        lastMessage = s;
    }

// toString makes it easy to create output of this class
    public String toString()
    {
        String retval;
        retval = "counter="+counter +" lastMessage="+ lastMessage + endOfLine;
        for (int i=0; i < list.size(); i++)
            retval += list.get(i) + endOfLine;
        return retval;

    }
}


EchoObjectClient.java


import java.io.IOException;
import java.io.InputStream;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
import java.io.OutputStream;
import java.util.Scanner;

public class EchoObjectClient extends EchoClient {

    void communicate(InputStream is, OutputStream os)
    {
        System.out.println("EchoObjectClient.communicate starts");

        UserInputs userInputs = new UserInputs();
        Scanner keyboard = new Scanner(System.in);
        String fromKeyboard= keyboard.nextLine();
        try
        {
            // Strange thing about the following 2 statements is that if you
            // switch them, our code hangs.  Apparently this is a known and documented issue

            ObjectOutputStream ooSocket = new ObjectOutputStream(os);
            ObjectInputStream oiSocket = new ObjectInputStream(is);


            while (!fromKeyboard.equals("quit"))
            {
                userInputs.addMsg(fromKeyboard);
                ooSocket.writeObject(userInputs);
                ooSocket.reset();  // This is needed when reusing the same object

                UserInputs ui = (UserInputs)oiSocket.readObject();
                System.out.println("received from server: "+ui);
                fromKeyboard = keyboard.nextLine();
            }

            oiSocket.close();
            ooSocket.close();
        }
        catch(IOException e)
        {
            System.out.println("EchoObjectClient.communicate IOException: " + e);
        }
        catch (ClassNotFoundException e)
        {
            System.out.println("EchoObjectClient.communicate ClassNotFoundException: " + e);
        }
        keyboard.close();
        System.out.println("Exitting communicate");
    }

    public static void main(String[] args)
    {
        EchoObjectClient echoObjectClient= new EchoObjectClient();
        echoObjectClient.startup(args);
        System.out.println("Exitting main");

    }

}



EchoObjectServer


import java.io.IOException;
import java.io.InputStream;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
import java.io.OutputStream;

public class EchoObjectServer extends EchoServer{

    void processStream(InputStream is, OutputStream os)
    {
        System.out.println("EchoObjectServer.processStream begins");
        ObjectInputStream input = null;
        ObjectOutputStream output = null;

        try
        {
            input = new ObjectInputStream(is);
            output = new ObjectOutputStream(os);
            UserInputs ui=(UserInputs)input.readObject();

            while (ui != null)
            {
                System.out.println("EchoObjectServer read: "+ui);
                output.writeObject(ui); // Echo data read
                ui=(UserInputs)input.readObject();
            }
        }
        catch (ClassNotFoundException e)
        {
            System.out.println("EchoObjectServer.processStream ClassNotFoundException: "+e);
        }
        catch (IOException e)
        {
            System.out.println("EchoObjectServer.processStream IOException: "+e);
        }
        finally
        {
            try
            { // I'm annoyed that I need try/catch for this
                input.close();
                output.close();
            }
            catch (IOException e)
            {}
        }
        System.out.println("Exitting EchoObjectServer.processStream");
    }

    public static void main(String[] args) {
        EchoObjectServer es = new EchoObjectServer();
        es.monitorServer();
        System.out.println("Exitting EchoServer");

    }

}



GetUrl.java

In this example, we are still using Socket programming, but we are using enough knowledge of HTTP to look like a primitive browser.


import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.PrintWriter;
import java.net.InetAddress;
import java.net.Socket;
import java.net.UnknownHostException;
import java.util.Scanner;

// Issue commands like:
//Host= russet.wccnet.org  Url=  /~chasselb/boys_names.txt
//Host= russet.wccnet.org  Url=  /~chasselb/girls_names.txt
//Host= www.wccnet.edu         Url=  /
//Host= www.yahoo.com          Url=  /



public class GetUrl {
  public static void main(String[] args) throws IOException {

        Socket urlSocket = null;
        PrintWriter out = null;
        BufferedReader in = null;
        InetAddress iaddr;
        String Url;
        String Host;

        Scanner keyboard = new Scanner(System.in);
        System.out.println("Enter the host(i.e. russet.wccnet.edu   ");
        Host = keyboard.next();
        System.out.println("Enter the URL (i.e. /~chasselb/boys_names.txt)");
        Url = keyboard.next();


        try
        {
            urlSocket = new Socket(Host, 80); // Web servers run on port 80
            iaddr = urlSocket.getLocalAddress();
            System.out.println("getHostName = " + iaddr.getHostName());
            System.out.println("getHostAddress = " + iaddr.getHostAddress());

            // Create in/out classes associated with the Open Socket

            // In many of my previous examples I have used PrintStream and Scanner
            // An alternative approach that you might see is PrintWriter and BufferedReader
            // These classes work in the Character world instead of the Byte world as we discussed
            // early on in the I/O section.  There was a time when java didn't have the Scanner class
            // and in those days, I used BufferedReader all of the time.

            // Instead of a PrintStream
            out = new PrintWriter(urlSocket.getOutputStream(), true);

            // Alternative to using the Scanner class
            in = new BufferedReader(
                   new InputStreamReader(
                       urlSocket.getInputStream()));

        }
        catch (UnknownHostException e)
        {
            System.err.println("Cant find host: "+ e);
            System.exit(1);
        }
        catch (IOException e)
        {
            System.err.println("Couldn't get I/O: " +e);
            System.exit(1);
        }

        String response;
        // a minimal HTTP request to fake out that we are a browser

        out.println("GET "+Url + " HTTP/1.1" + "\r\n" +
                    "Host: " + Host + "\r\n" + "\r\n");


        while ((response = in.readLine()) != null) // Read from Socket
        {
            System.out.println(response);
        }

        out.close(); // Close output stream side of the socket
        in.close();  // Close input stream side of socket
        urlSocket.close();  // Close the socket
  }// end of main
}// end of getUrl class





URLReader.java

Java provides a URL class that allows you to use HTTP at a little higher level than Socket programming. Note that the URL constructor includs the URL string. By calling openStream, you can obtain an InputStream class instance. From this class, you can read back your results (probably the contents of an Html file). Note that you don't need to know any HTTP command sequences. Also you don't have to strip off any HTTP Server protocol wrappers like you might have in GetUrl.java above.


import java.io.BufferedReader;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.net.URL;
import java.util.Scanner;

// Try:
//   URLs like:
//      russet.wccnet.org/~chasselb/boys_names.txt
//      russet.wccnet.org/~chasselb/girls_names.txt
//      wccnet.edu
//      yahoo.com


public class URLReader {
  public static void main(String[] args) throws Exception
  {
    String urlString;
    URL myUrl;
    InputStream inStream;

    Scanner keyboard= new Scanner(System.in);
    System.out.println("Enter URL (i.e. yahoo.com)");
    urlString = keyboard.next();

    myUrl = new URL("http://"+urlString);

    inStream = myUrl.openStream();

    Scanner in = new Scanner(inStream);

    while (in.hasNextLine())
        System.out.println(in.nextLine());

    in.close();
  }
}





Another Thing that can be used if you need to add parameters:

urlString += "?equation="+URLEncoder.encode("x=y+x/4");

ParseURL.java


import java.net.*;
import java.io.*;

public class ParseURL {
    public static void main(String[] args) throws Exception {
        URL aURL = new URL("http://java.sun.com:80/docs/books/tutorial/intro.html#DOWNLOADING");
        System.out.println("protocol = " + aURL.getProtocol());
        System.out.println("host = " + aURL.getHost());
        System.out.println("filename = " + aURL.getFile());
        System.out.println("port = " + aURL.getPort());
        System.out.println("ref = " + aURL.getRef());
    }
}


Snoop:

This program can be used to watch the the conversation between a server and a client.


import java.net.*;
import java.io.*;

public class SnoopMom {
    public static void main(String[] args) throws IOException {

     int portNum = 4444;
     InetAddress iaddr=null;
     ServerSocket serverSocket = null;
     String host="gettysburg.wccnet.edu";
     int hostPort = 80;

     if (args.length > 0)
     {
         portNum = Integer.parseInt(args[0]);
     }

     try {
            serverSocket = new ServerSocket(portNum);
            iaddr = InetAddress.getLocalHost();
            System.out.println("Host:" + iaddr.getHostName()+
                 " ipaddr=" + iaddr.getHostAddress()+
                 " portnum="+ portNum);
        }
     catch (IOException e)
        {
            System.err.println("Socket Err:" + e);
            System.exit(1);
        }

     boolean listening = true;
     Socket nextSock;
     int nThreadCount=0;

     while (listening)
     {
         nextSock = serverSocket.accept();
         Thread client2server, server2client;
         System.out.println(nThreadCount +" Another Thread Created");

       // Create a thread to process incoming connection
         client2server = new Client2ServerChild(nextSock, host, hostPort, nThreadCount++);
         client2server.start();

      }

      serverSocket.close();
    }
}


//**********************************************


import java.net.*;
import java.io.*;

public class Client2ServerChild extends Thread {
    private Socket inSocket = null;
    private Socket outSocket = null;
    int myIndex;
    //BufferedOutputStream out=null;
    //BufferedInputStream in = null;
    BufferedReader in = null;
    PrintStream out = null;
    Server2ClientChild server2client=null;

    public Client2ServerChild(Socket s, String host, int hostPort, int me)
    throws IOException
    {
    	inSocket = s;
    	outSocket = new Socket(host, hostPort);
    	System.out.println("Socket created for "+host + " " + hostPort);
        myIndex= me;
        server2client = new Server2ClientChild(inSocket, outSocket, me);
        server2client.start();
    }

    public void run()
    {
       int max_size=1024;
       byte[] buffer = new byte[max_size];
       int numRead;
       String str;

       System.out.println("Client2Server running");

       try {
            out = new PrintStream(outSocket.getOutputStream());

            in = new BufferedReader( new InputStreamReader(
            		inSocket.getInputStream()));
            System.out.println("******** Client2Server *****");
            int count = 1;
            do
            {
            	str = in.readLine();
            	if (count++ == 2)            	
            		str = "Host: gettysburg.wccnet.edu:80";
            	
            	out.println(str);	
            	System.out.println(str);
            	
            } while (str != null);
            System.out.println("**********************");
           }
       catch (IOException e)
           {
             System.out.println("Client2ServerChild Err: " + e);
             e.printStackTrace();
           }
       finally
           {
             try
             { // I'm annoyed that I need try ... catch to keep the compiler happy here
                out.close();
                in.close();
                System.out.println(myIndex + ": Thread Exitting");
             } catch (Exception e){}
           }
       System.out.println("Client2Server exitting");
    }// end of run routine
}

// ***********************************************

import java.net.*;
import java.io.*;

public class Server2ClientChild extends Thread {
	private Socket inSocket = null;
    private Socket outSocket = null;
    int myIndex;
    BufferedOutputStream out=null;
    BufferedInputStream in = null;

    public Server2ClientChild(Socket inSocket, Socket outSocket, int me)
    {
       this.inSocket = inSocket;
       this.outSocket = outSocket;
       myIndex= me;
    }

    public void run()
    {
       int max_size=1024;
       byte[] buffer = new byte[max_size];
       int numRead;
       System.out.println("Server2Child running");

       try {
            out = new BufferedOutputStream(inSocket.getOutputStream());

            in = new BufferedInputStream(
            		outSocket.getInputStream());

            do
            {
            	numRead = in.read(buffer, 0, max_size);
            	if (numRead > 0)
            	{
            		out.write(buffer, 0, max_size);
            		System.out.println("******** Server2Client *****");
            		System.out.write(buffer,0, max_size);
            		System.out.println("**********************");
            	}
            } while (numRead > 0);
           }
       catch (IOException e)
           {
             System.out.println("Server2ClientChild Err: " + e);
             e.printStackTrace();
           }
       finally
           {
             try
             { // I'm annoyed that I need try ... catch to keep the compiler happy here
                out.close();
                in.close();
                System.out.println(myIndex + ": Thread Exitting");
             } catch (Exception e){}
           }

       System.out.println("Server2Child exitting");
    }// end of run routine
}





ShowDocument.java


package networking;

import java.applet.AppletContext;
import java.awt.Button;
import java.awt.Choice;
import java.awt.GridLayout;
import java.awt.Label;
import java.awt.TextField;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.net.MalformedURLException;
import java.net.URL;

import javax.swing.JApplet;

public class ShowDocument extends JApplet
                          implements ActionListener {
    TextField urlField;
    Choice choice;
    AppletContext context;

    public void init() {

    context = getAppletContext();
    setLayout(new GridLayout(0,1));

    Label label1 = new Label("URL of document to show:",
                                 Label.LEFT);
    add(label1);

    urlField = new TextField("http://yahoo.com/", 50);
    urlField.addActionListener(this);
    add(urlField);

    Label label2 = new Label("Window/frame to show it in:",
                                 Label.LEFT);
    add(label2);

    choice = new Choice();
    choice.addItem("(browser's choice)"); //don't specify
    choice.addItem("My Personal Window"); //a window named
                                        //"My Personal Window"
    choice.addItem("_blank"); //a new, unnamed window
    choice.addItem("_parent");
    choice.addItem("_top"); //the Frame that contained this applet
    add(choice);

    Button button = new Button("Show document");
    button.addActionListener(this);
    add(button);

    }

    public void actionPerformed(ActionEvent event) {
        String urlString = urlField.getText();
        URL url = null;
        try {
            url = new URL(urlString);
            context.showStatus("Mine: "+urlString);
            if (url != null) {
                if (choice.getSelectedIndex() == 0)
                    context.showDocument(url);
                else
                    context.showDocument(url,
                                  choice.getSelectedItem());
                }
            }
        catch (MalformedURLException e)
            {
                System.err.println("Malformed URL: " + urlString);
            }
    }
}






Datagram Examples -I have some examples that I don't plan to preset. These examples make use of datagrams

Exercises - These are not assignments for this class

1. Create a Server that delivers One Liners. You can have your server cycle through your One-liners, or you can use a random number approach to delivering one-liners. Provide the following commands for your One-Liner Service:
  - Count - This command will return the Number of One-Liners
  - Fetch N - This command will return the N'th One-Liner
  - Fetch - This command will return a Random One-Liner
  - Bye
Your Server should be a Multi-Threaded Server. A sample list of one-liners follows:


Life is wonderful. Without it we'd all be dead.
Daddy, why doesn't this magnet pick up this floppy disk?
Give me ambiguity or give me something else.
I.R.S.: We've got what it takes to take what you've got!
We are born naked, wet and hungry. Then things get worse.
Make it idiot proof and someone will make a better idiot.
He who laughs last thinks slowest!
Always remember you're unique, just like everyone else.
"More hay, Trigger?" "No thanks, Roy, I'm stuffed!"
A flashlight is a case for holding dead batteries.
Lottery: A tax on people who are bad at math.
Error, no keyboard - press F1 to continue.
There's too much blood in my caffeine system.
Artificial Intelligence usually beats real stupidity.
Hard work has a future payoff. Laziness pays off now.
"Very funny, Scotty. Now beam down my clothes."
Puritanism: The haunting fear that someone, somewhere may be happy.
Consciousness: that annoying time between naps.
Don't take life too seriously, you won't get out alive.
I don't suffer from insanity. I enjoy every minute of it.
Better to understand a little than to misunderstand a lot.
The gene pool could use a little chlorine.
When there's a will, I want to be in it.
Okay, who put a "stop payment" on my reality check?
We have enough youth, how about a fountain of SMART?
Programming is an art form that fights back.
"Daddy, what does FORMATTING DRIVE C mean?"
All wiyht. Rho sritched mg kegtops awound?
My mail reader can beat up your mail reader.
Never forget: 2 + 2 = 5 for extremely large values of 2.
Nobody has ever, ever, EVER learned all of WordPerfect.
To define recursion, we must first define recursion.
Good programming is 99% sweat and 1% coffee.
Home is where you hang your @
The E-mail of the species is more deadly than the mail.
A journey of a thousand sites begins with a single click.
You can't teach a new mouse old clicks.
Great groups from little icons grow.
Speak softly and carry a cellular phone.
C:\ is the root of all directories.
Don't put all your hypes in one home page.
Pentium wise; pen and paper foolish.
The modem is the message.
Too many clicks spoil the browse.
The geek shall inherit the earth.
A chat has nine lives.
Don't byte off more than you can view.
Fax is stranger than fiction.
What boots up must come down.
Windows will never cease.   (ed. oh sure...)
In Gates we trust.    (ed.  yeah right....)
Virtual reality is its own reward.
Modulation in all things.
A user and his leisure time are soon parted.
There's no place like http://www.home.com
Know what to expect before you connect.
Oh, what a tangled website we weave when first we practice.
Speed thrills.
Give a man a fish and you feed him for a day; teach him to use the Net and he won't bother you for weeks.



2. Write a Cmd Server --- Executes FileManger (see the I/O section) on another server. .
3. Add 2 new commands to the Cmd Server : Fetch, Put ----
First line of input contains command along with the relavent filename(Restrict to text)
4. Create an ATM Server. Each ATM client simulates an ATM machine. The ATM server logs the requests in a master log file.
5. Write a Rock, Paper, Scissors Server.

Last Modified: July 22, 2014 9:39 PM