500 likes | 609 Views
Introduction to Networking Using Java. CMSC 432 Shon Vick. Agenda. Look at Network in Java programming examples The examples are somewhat more involved than those in Budd Orange Chapter 22 Examine Advanced I/O in some detail. Networking.
E N D
Introduction to NetworkingUsing Java CMSC 432 Shon Vick
Agenda • Look at Network in Java programming examples • The examples are somewhat more involved than those in Budd Orange Chapter 22 • Examine Advanced I/O in some detail
Networking • Using the networking capabilities provided in the Java environment is quite easy because of the object orientation • We will see how to use Sockets and more sophisticated networking • You may have already used these facilities in oher langauges
Sockets • There are other relatively high-level mechanism for accessing resources on the Internet but lets look at lower-level network communication • Client – uses some service • Server - provides some service • TCP provides a reliable, point-to-point communication channel for client-server apps
What Is a Socket? • A socket is one endpoint of a two-way communication link between two programs running on the network. • A socket is bound to a port number so that the TCP layer can identify the application that data is destined to be sent.
How do Socket work? • A server runs on a specific computer and has a socket that is bound to a specific port number. • Client knows the hostname and port of server and tries to make a connection request
Connection established • If the server accepts the connection it gets a new socket bound to a different port. • It needs a new socket (and consequently a different port number) so that it can continue to listen to the original socket
How does Java support Sockets • The java.net package provides a class, Socket, that implements one side of a two-way connection between your Java program and another program on the network • It also includes the ServerSocket class, which implements a socket that servers can use to listen for and accept connections to client
Echo Echo Echo import java.io.*; import java.net.*; public class EchoClient { public static void main(String[] args) throws IOException { Socket echoSocket = null; PrintWriter out = null; BufferedReader in = null; // …
Establish the Socket connection Output Port Host try { echoSocket = new Socket(“avatar ", 7777); out = new PrintWriter(echoSocket.getOutputStream(), true); in = new BufferedReader(new InputStreamReader(echoSocket.getInputStream())); } catch … Input
Need to Catch Exceptions } catch (UnknownHostException e) { System.err.println("Don't know about host: avatar."); System.exit(1); } catch (IOException e) { System.err.println("Couldn't get I/O for " + "the connection to: avatar."); System.exit(1); }
Simple Socket Example Set up a mechanism to read from standard input BufferedReader stdIn = new BufferedReader( new InputStreamReader(System.in)); String userInput; while ((userInput = stdIn.readLine()) != null) { out.println(userInput); System.out.println("echo: " + in.readLine()); } Read from standard input Write to Server Output what’s read back from Server
Close up Shop on Client side out.close( ); in.close( ); stdIn.close( ); echoSocket.close( );
Basic Steps • Open a socket. • Open an input stream and output stream to the socket. • Read from and write to the stream according to the server's protocol. • Close the streams. • Close the socket.
Same Basic Steps • This client program is straightforward and simple because the Echo server implements a simple protocol • Even with more complicated protocols such as a HTTP server, your client program while more complicated will follow the same basics as this simple example
Server • A server must open a SeverSocket ServerSocket server = new ServerSocket( 7777 ); • Call accept on that socket creating a new socket Socket socket = server.accept(); • Socket acts as socket from client
Networking Continued • We’ve looked at a few simple example of networking using sockets • Lets look at them again, but this time lets look at them a bit more deeply • We said that one way to think of a socket is that it’s just some plumbing that connects a client and server
If a socket is a pipe … We could conceptualize this as so: Ports Client Server The things flowing through the Plumbing The Socket Plumbing
The Answer Is .. • A Number of things can conceptually flow through the pipe • We looked at several examples last time • The first was a simple echo program – a very simple protocol – give me back what I gave you • What flowed through the pipe in each of these cases • We also looked at simpleprotocol example
Objects flow through the Pipe • If we want to have objects flowing over the pipe then there must be a mechanism for • Objects to be written by the server • Objects to be read by the client • Consider the example of a client and server communicating via some protocol
A Protocol Client Example public class Client { Socket socket = new Socket( "127.0.0.1", 9999 ); // ObjectInputStream input = new ObjectInputStream(socket.getInputStream() ); // read using serialization NewProtocol protocol = (NewProtocol)(input.readObject() ); System.out.println(“Protocol: “ + protocol); socket.close();
The newprotocol Server class ThreadedSocket extends Thread { // here is where all the real work is done. private Socket socket; ThreadedSocket( Socket socket ) { this.socket = socket; //… ObjectOutputStream output = new ObjectOutputStream(socket.getOutputStream() ); output.writeObject( protocol );
Reading and Writing Objects • An ObjectOutputStream writes primitive data types and graphs of Java objects to an OutputStream. • The objects can be read (reconstituted) using an ObjectInputStream. • General Mechanism • This works for the sockets as was just shown but is actually more general • Persistent storage of objects can be accomplished by using a file for the stream.
File example • For example to write an object that can be read by the example in ObjectInputStream FileOutputStream ostream = new FileOutputStream(“foo.bar"); ObjectOutputStream p = new ObjectOutputStream(ostream); p.writeInt(12345); p.writeObject("Today"); p.writeObject(new Date()); p.flush(); ostream.close();
The read counterpart FileInputStream istream = new FileInputStream(" foo.bar "); ObjectInputStream p = new ObjectInputStream(istream); int i = p.readInt(); String today = (String)p.readObject(); Date date = (Date)p.readObject(); istream.close();
Some Framework • Only objects that support the java.io.Serializable interface can be written to streams. • The class of each serializable object is encoded including the class name and signature of the class, the values of the object's fields and arrays, and the closure of any other objects referenced from the initial objects • This relates to introspection/reflection which we will discuss later
More about the Framework • The default deserialization mechanism for objects restores the contents of each field to the value and type it had when it was written. • Marshalling of Objects (Serialize) • Un marshaling of Object (Serialize)
Still More • Fields declared as transient or static are ignored by the deserialization process. • References to other objects cause those objects to be read from the stream as necessary. • Graphs of objects are restored correctly using a reference sharing mechanism. • New objects are always allocated when deserializing, which prevents existing objects from being overwritten
Strings flowing through the Pipe • Say we want to have strings (i.e. character data) flowing over the pipe then there must be a mechanism for • Strings to be written by the server • Objects to be read by the client • Consider the Echo example
Echo Echo Echo import java.io.*; import java.net.*; public class EchoClient { public static void main(String[] args) throws IOException { Socket echoSocket = null; PrintWriter out = null; BufferedReader in = null; // …
Establish the Socket connection Output Port Host try { echoSocket = new Socket(“avatar ", 7777); out = new PrintWriter(echoSocket.getOutputStream(), true); in = new BufferedReader(new InputStreamReader(echoSocket.getInputStream())); } catch … Input
Simple Socket Example Set up a mechanism to read from standard input BufferedReader stdIn = new BufferedReader( new InputStreamReader(System.in)); String userInput; while ((userInput = stdIn.readLine()) != null) { out.println(userInput); System.out.println("echo: " + in.readLine()); } Read from standard input Write String to Server Read String that’s sent back from Server
A String Based Protocol? Server: "Knock knock!" Client: "Who's there?" Server: "Dexter." Client: "Dexter who?" Server: "Dexter halls with boughs of holly." Client: "Groan."
The Knock Knock Protocol • The KnockKnockProtocol class implements the protocol that the client and server use to communicate. • This class keeps track of where the client and the server are in their conversation and serves up the server's response to the client's statements.
Protocol Needs State and Constants import java.net.*; import java.io.*; public class KnockKnockProtocol { private static final int WAITING = 0; private static final int SENTKNOCKKNOCK = 1; private static final int SENTCLUE = 2; private static final int ANOTHER = 3; private static final int NUMJOKES = 5; private int state = WAITING; private int currentJoke = 0; Constants State
Some More Invariants private static final String[] clues = { "Turnip", "Little Old Lady", "Atch", "Who", "Who" }; private static final String[] answers = { "Turnip the heat, it's cold in here!", "I didn't know you could yodel!", "Bless you!", "Is there an owl in here?", "Is there an echo in here?" };
The Actual Protocol Part 1 public String processInput(String theInput) { String theOutput = null; if (state == WAITING) { theOutput = "Knock! Knock!"; state = SENTKNOCKKNOCK; } else if (state == SENTKNOCKKNOCK) { if (theInput.equalsIgnoreCase("Who's there?")) { theOutput = clues[currentJoke]; state = SENTCLUE; } else { theOutput = "You're supposed to say \"Who's there?\"! " + "Try again. Knock! Knock!";
The Actual Protocol Part 2 } else if (state == SENTCLUE) { if (theInput.equalsIgnoreCase(clues[currentJoke] + " who?")) { theOutput = answers[currentJoke] + " Want another? (y/n)"; state = ANOTHER; } else { theOutput = "You're supposed to say \"" + clues[currentJoke] + " who?\"" + "! Try again. Knock! Knock!"; state = SENTKNOCKKNOCK; } } else if (state == ANOTHER) {
The Actual Protocol Part 3 } else if (state == ANOTHER) { if (theInput.equalsIgnoreCase("y")) { theOutput = "Knock! Knock!"; if (currentJoke == (NUMJOKES - 1)) currentJoke = 0; else currentJoke++; state = SENTKNOCKKNOCK; } else { theOutput = "Bye."; state = WAITING; } } return theOutput; } }
Using the Protocol • All client/server pairs must have some protocol by which they speak to each other; otherwise, the data that passes back and forth would be meaningless. • The protocol that your own clients and servers use depends entirely on the communication required by them to accomplish the task
Use by the Client • The KnockKnockClient class implements the client program that speaks to the KnockKnockServer. KnockKnockClient is based on the Echo client we saw last time. • The communication between the client and the server • The server must first speak • Client must listen first
Just like before we need both directions Socket kkSocket = new Socket(“avatar", 4444); // .. out = new PrintWriter(kkSocket.getOutputStream(), true); in = new BufferedReader( new InputStreamReader(kkSocket.getInputStream())); // …
The Client Using the Protocol while ((fromServer = in.readLine()) != null) { System.out.println("Server: " + fromServer); if (fromServer.equals("Bye.")) break; fromUser = stdIn.readLine(); if (fromUser != null) { System.out.println("Client: " + fromUser); out.println(fromUser); } }
The Server Using the Protocol • Server program begins by creating a new ServerSocket object to listen on a specific port • try { • serverSocket = new ServerSocket(4444); • } catch (IOException e) { • System.out.println("Could not listen on port: 4444"); • System.exit(-1); • }
Wait for a connection Socket clientSocket = null; try { clientSocket = serverSocket.accept(); } catch (IOException e) { System.out.println("Accept failed: 4444"); System.exit(-1); }
Set up the streams for the pipe PrintWriter out = new PrintWriter( clientSocket.getOutputStream(), true); BufferedReader in = new BufferedReader( new InputStreamReader( clientSocket.getInputStream())); String inputLine, outputLine;
Start the Conversation // initiate conversation with client KnockKnockProtocol kkp = new KnockKnockProtocol(); outputLine = kkp.processInput(null); out.println(outputLine);
Use the Protocol while ((inputLine = in.readLine()) != null) { outputLine = kkp.processInput(inputLine); out.println(outputLine); if outputLine.equals("Bye.")) break; }
Selected References • Advanced Techniques for Java Developers Chapter 4 • http://java.sun.com/products/jdk/1.2/docs/api/java/io/ObjectInputStream.html • http://java.sun.com/docs/books/tutorial/networking/index.html
More References • The Java Programming Language , K.Arnold and J. Gosling , Addison-Wesley , 1996 • http://java.sun.com/products/jdk/1.2/docs/