820 likes | 971 Views
Lecture 8. Java Distributed Computing. Cheng-Chia Chen. Distributed Computing. Network programming JDBC Servlets & JSPs Remote Method Invocation (RMI) Others not covered: CORBA Enterprise JavaBeans (EJB) JINI JavaSpaces. Network programming.
E N D
Lecture 8. Java Distributed Computing Cheng-Chia Chen
Distributed Computing • Network programming • JDBC • Servlets & JSPs • Remote Method Invocation (RMI) • Others not covered: • CORBA • Enterprise JavaBeans (EJB) • JINI • JavaSpaces
Network programming • Historically error-prone, difficult, complex • but network programming in java is rather easy • IO stream library works quite well for TCP/IP. • Threading is also very useful and relatively easy here • References: • The java tutorial, Trail: Custom Networking • http://java.sun.com/docs/books/tutorial/index.html • Thinking in java, ch 15 http://www.eckelobjects.com/TIJ2/index.html. • “Java Network Programming” by Elliotte Rusty Harold, O’Reilly Books, 2nd Edition 2000. visit http://www.ibooks.com for a free online reference.
(Peer to Peer) Protocol interfaces InterNet physical layer physical layer Networking Basics • TCP/IP Network Protocol
TCP and UDP • TCP (Transmission Control Protocol) is a connection-based protocol that provides a reliable flow of data between two computers. • UDP (User Datagram Protocol) is a protocol that sends independent packets of data, called datagrams, from one computer to another with no guarantees about arrival. UDP is not connection-based like TCP.
Identifying a Machine • Uniquely identify a machine from all the others in the world • IP (Internet Protocol) address that can exist in two forms: • DNS (Domain Name System) form: xml.cs.nccu.edu.tw • “Dotted quad” (IP) form: 140.119.162.230 • Represented internally by 32-bit number (4 bytes) • 4.3 billion possibilities. • IPV6 : 128-bit coming… • static InetAddress.getByName(String) produces Java object containing address
server Client InputStream OutputStream OutputStream InputStream Socket connection (full duplex) Servers & Clients • Two machines must connect • Server waits around for connection • Client initiates connection • Once the connection is made, server & client look identical • Both ends are turned into InputStreamand OutputStreamobjects, which can then be converted to Reader and Writer objects
Testing w/o a Network • Here, we have no network • Also, you may not trust your program enough yet. • “localhost”: the “local loopback” IP address for testing without a network InetAddress addr = InetAddress.getByName(null); • Equivalently: InetAddress.getByName("localhost"); • Or using the reserved IP number for the loopback: InetAddress.getByName("127.0.0.1");
WhoAmI // Finds out your network address when // you're connected to the Internet. import java.net.*; public class WhoAmI { public static void main(String[] args) throws Exception { if(args.length != 1) { System.err.println( "Usage: WhoAmI MachineName"); System.exit(1); } InetAddress a = InetAddress.getByName(args[0]); System.out.println(a); } }
Port: Unique “Place” in a Machine • IP address isn’t enough to identify a unique server • Many servers can exist on one machine • IP machines also contain port numbers • When you set up client and server, you must specify IP address and port, so they can find each other • Not a physical location, but a software abstraction to represent a service • There are 65536 ports in a machine • 0-1023 reserved, others usable • 80 HTTP; 110 POP3; • 20,21 ftp; 25 smtp; • 23 telnet, 119 nntp …
server Client InputStream OutputStream OutputStream InputStream Socket connection (full duplex) Sockets • Software abstraction used to represent the “terminals” of a connection between two machines • Java provides a class abstraction : java.io.Socket • Socket is the actual 2-way connector. Can initiate a connection with a server • ServerSocket isn’t really a socket but more of a “ServerConnector” that produces a Socket as the return value of accept( ), which waits for a connection. • In the end, you get a Socket on each machine
Just Like Files... • Once you have a Socket, you call getInputStream( ) and getOutputStream( ) to produce the corresponding InputStream and OutputStream objects • You convert these to readers and writers, wrap them in a BufferedReader or BufferedWriter and PrintWriter • From then on, it’s like reading and writing any other IO stream!
Simple Server & Client //: Very simple server that just echoes whatever the client sends. import java.io.*; import java.net.*; public class JabberServer { // Choose a port outside of the range 0-1023: public static final int PORT = 8080; public static void main(String args[]) throws IOException { ServerSocket s = new ServerSocket(PORT); System.out.println("Started: " + s);
try { // Blocks until a connection occurs: Socket socket = s.accept(); try { System.out.println( "Connection accepted: "+ socket); BufferedReader in = new BufferedReader( new InputStreamReader( socket.getInputStream())); // Output is automatically flushed by PrintWriter: PrintWriter out = new PrintWriter( new BufferedWriter( new OutputStreamWriter ( socket.getOutputStream())),true);
while (true) { // main server response String str = in.readLine(); if (str.equals("END")) break; System.out.println("Echoing: " + str); out.println(str); } // Always close the two sockets... } finally { System.out.println("closing..."); socket.close(); } } finally { s.close(); } } }
The client program // Thinking in Java c15, JabberClient.java // Very simple client that just sends lines to the server and reads lines // that the server sends. import java.net.*; import java.io.*; public class JabberClient { public static void main(String args[]) throws IOException { // "Local Loopback" IP address: InetAddress addr = InetAddress.getByName(null); System.out.println("addr = " + addr); // Unlike ServerSocket, client needn’t specify its local port, which is allocated dynamically by machine. Socket socket =new Socket(addr, JabberServer.PORT); // Guard everything in a try-finally to make sure that the socket is closed:
try { System.out.println("socket = " + socket); BufferedReader in = new BufferedReader( new InputStreamReader( socket.getInputStream())); // Output is automatically flushed by PrintWriter: PrintWriter out = new PrintWriter( new BufferedWriter( new OutputStreamWriter (socket.getOutputStream() ) ), true); for(int i = 0; i < 10; i ++) { out.println(“sending " + i); String str = in.readLine(); System.out.println(str); } out.println("END"); } finally { System.out.println("closing..."); socket.close();} } }
Serving Multiple Clients via Threads // A server that uses multithreading to handle any number of clients. import java.io.*; import java.net.*; class ServeOneJabber extends Thread { private Socket socket; private BufferedReader in; private PrintWriter out; public ServeOneJabber(Socket s) throws IOException { socket = s; in = new BufferedReader( new InputStreamReader (socket.getInputStream())); // Enable auto-flush: out = new PrintWriter(new BufferedWriter( new OutputStreamWriter ( socket.getOutputStream())), true); // If any of the above calls throw an exception, the caller is responsible // for closing the socket. Otherwise the thread will close it. }
public void run() { try { while (true) { String str = in.readLine(); if (str.equals("END")) break; System.out.println("Echoing: " + str); out.println(str); } System.out.println("closing..."); } catch (IOException e) { } finally { try {socket.close(); } catch(IOException e) {} } } }
MultiJabberServer public class MultiJabberServer { static final int PORT = 8080; public static void main(String[] args) throws IOException { ServerSocket s = new ServerSocket(PORT); System.out.println("Server Started"); try { while(true) { // wait for a connection established: Socket socket = s.accept(); try { new ServeOneJabber(socket).start(); } catch(IOException e) { // If it fails, close the socket, otherwise the thread will close it: socket.close(); } } } finally { s.close(); } } }
JabberClientThread // Client that tests the MultiJabberServer by starting up multiple clients. import java.net.*; import java.io.*; class JabberClientThread extends Thread { private Socket socket; private BufferedReader in; private PrintWriter out; private static int counter = 0; private int id = counter++; private static int threadcount = 0; public static int threadCount() { return threadcount; } public JabberClientThread(InetAddress addr) { System.out.println("Making client " + id); threadcount++; try { socket = new Socket(addr, MultiJabberServer.PORT); } catch(IOException e) { // If the creation of the socket fails, nothing needs to be cleaned up. }
try { in = new BufferedReader( new InputStreamReader ( socket.getInputStream())); // Enable auto-flush: out = new PrintWriter( new BufferedWriter( new OutputStreamWriter( socket.getOutputStream())), true); start(); } catch(IOException e) { // The socket should be closed on any failures other than the socket // constructor: try { socket.close(); } catch(IOException e2) {} } // Otherwise the socket will be closed by // the run() method of the thread. }
public void run() { try { for(int i = 0; i < 25; i++) { out.println("Client " + id + ": " + i); String str = in.readLine(); System.out.println(str); } out.println("END"); } catch(IOException e) {} finally { // Always close it: try { socket.close();} catch(IOException e) {} threadcount--; // Ending this thread } } }
MultiJabberClient public class MultiJabberClient { static final int MAX_THREADS = 40; public static void main(String[] args) throws IOException, InterruptedException { InetAddress addr = InetAddress.getByName(null); while(true) { if(JabberClientThread.threadCount() < MAX_THREADS) new JabberClientThread(addr); Thread.currentThread().sleep(100); // Why not just sleep(100)? } } }
Port Warning • Problem: program works fine, except when client is behind a firewall • Firewall doesn’t like to see anything but ordinary network connections to WWW server via its standard http port 80 • Servlets solve the problem
User Datagram Protocol (UDP) • Previous examples used Transmission Control Protocol (TCP). • Very high reliability, message will always get there. • Also high overhead • User Datagram Protocol (UDP) is an unreliable protocol which is much faster, but the messages won’t always get there • c.f.: • TCP Telephone system • UDP postal service
Datagrams • You make your own packets and write the address on the outside, send it • Based on packet contents, recipients decide whether they got everything, sends a message if they didn’t, and you retransmit in that case. • Reliability must be enforced by your program, not by the UDP protocol • Java APIs provided in two classes: • java.net.DatagramPacket • java.net.DatagramSocket
DatagramPacket • Encapsulation of data(packet) to be received/transmitted and related information. • Constructors: • // for receiving packets • DatagramPacket(byte[] data [ [, int offset] , int length]) • // for sending packets • DatagramPacket(byte[] data [ [, int offset], int length], • InetAddress ia ,int port )
DatagramPacket Methods InetAddress getAddress() Returns the IP address of the peer machine. byte[] getData() Returns the data buffer. int getLength()Returns the length of the data. int getOffset() Returns the offset of the data to be sent/received. int getPort() Returns the port number on the remote host. SocketAddress getSocketAddress()Gets the SocketAddress (usually IP address + port number) of the remote host. void setAddress(InetAddress iaddr) void setData(byte[] buf [, int offset, int length]) void setLength(int length) void setPort(int iport) void setSocketAddress(SocketAddress )
DatagramSocket • represents a socket for sending and receiving datagram packets • Constructor • // bind to local IP laddr and port port or local SocketAddr bindaddr • // info not given => allocated by machine • DatagramSocket([ int port [,InetAddress laddr]] ) • DatagramSocket(SocketAddress bindaddr ) • Methods • // for local info manipulation • void bind(SocketAddress), • isBound(), • getLocalAddress(), getLocalPort(), getLocalSocketAddress()
// for remote info manipulation • // dedicated to this remote socket address only • connect(InetAddress, int), connect(SocketAddress), • disconnect(), • isConnected() : // return null/-1 if not connected. • getInetAddress(), getPort(), getRemoteSocketAddress() • //send/receive data • send(DatagramPacket) • receive(DatagramPacket) • // others • isClosed() • getBroadcast(), setBroadcast(boolean), • getSoTimeout(), setSoTimeout(int),…
// Fig.18.7: Client.java // Client that sends and receives packets to/from a server. import java.io.*; import java.net.*;import java.awt.*; import java.awt.event.*;import javax.swing.*; publicclass Client extends JFrame { private JTextField enterField; private JTextArea displayArea; private DatagramSocket socket; // set up GUI and DatagramSocket public Client() { super( "Client" ); Container container = getContentPane(); enterField = new JTextField( "Type message here" ); enterField.addActionListener( new ActionListener() { publicvoid actionPerformed( ActionEvent event ) {
// create and send packet try { displayArea.append( "\nSending packet containing: " + event.getActionCommand() + "\n" ); // get message from textfield and convert to byte array String message = event.getActionCommand(); byte data[] = message.getBytes(); // create sendPacket DatagramPacket sendPacket = new DatagramPacket( data, data.length, InetAddress.getLocalHost(), 5000 ); socket.send( sendPacket ); // send packet displayArea.append( "Packet sent\n" ); displayArea.setCaretPosition( displayArea.getText().length() ); } // process problems creating or sending packet catch ( IOException ioException ) { displayMessage( ioException.toString() + "\n" ); ioException.printStackTrace(); }
} // end actionPerformed } // end inner class ); // end call to addActionListener container.add( enterField, BorderLayout.NORTH ); displayArea = new JTextArea(); container.add( new JScrollPane( displayArea ), BorderLayout.CENTER ); setSize( 400, 300 ); setVisible( true ); // create DatagramSocket for sending and receiving packets try { socket = new DatagramSocket(); } // catch problems creating DatagramSocket catch( SocketException socketException ) { socketException.printStackTrace(); System.exit( 1 ); }
} // end Client constructor // wait for packets to arrive from Server, display packet contents privatevoid waitForPackets() { while ( true ) { // loop forever // receive packet and display contents try { // set up packet byte data[] = newbyte[ 100 ]; DatagramPacket receivePacket = new DatagramPacket( data, data.length ); socket.receive( receivePacket ); // wait for packet // display packet contents displayMessage( "\nPacket received:" + "\nFrom host: " + receivePacket.getAddress() + "\nHost port: " + receivePacket.getPort() + "\nLength: " + receivePacket.getLength() + "\nContaining:\n\t" + new String( receivePacket.getData(), 0, receivePacket.getLength() ) ); }
// process problems receiving or displaying packet catch( IOException exception ) { displayMessage( exception.toString() + "\n" ); exception.printStackTrace(); } } // end while } // end method waitForPackets // utility method called from other threads to manipulate // displayArea in the event-dispatch thread privatevoid displayMessage( final String messageToDisplay ) { // display message from event-dispatch thread of execution SwingUtilities.invokeLater( new Runnable() { // inner class to ensure GUI updates properly publicvoid run() // updates displayArea { displayArea.append( messageToDisplay ); displayArea.setCaretPosition( displayArea.getText().length() ); }
} // end inner class ); // end call to SwingUtilities.invokeLater } publicstaticvoid main( String args[] ) { Client application = new Client(); application.setDefaultCloseOperation( JFrame.EXIT_ON_CLOSE ); application.waitForPackets(); } } // end class Client
// Fig.18.6: Server.java // Server that receives and sends packets from/to a client. import java.io.*; import java.net.*;import java.awt.*; import java.awt.event.*;import javax.swing.*; publicclass Server extends JFrame { private JTextArea displayArea; private DatagramSocket socket; // set up GUI and DatagramSocket public Server() { super( "Server" ); displayArea = new JTextArea(); getContentPane().add( new JScrollPane( displayArea ), BorderLayout.CENTER ); setSize( 400, 300 ); setVisible( true ); // create DatagramSocket for sending and receiving packets try { socket = new DatagramSocket( 5000 ); }
// process problems creating DatagramSocket catch( SocketException socketException ) { socketException.printStackTrace(); System.exit( 1 ); } } // end Server constructor // wait for packets to arrive, display data and echo packet to client privatevoid waitForPackets() { while ( true ) { // loop forever // receive packet, display contents, return copy to client try {// set up packet byte data[] = newbyte[ 100 ]; DatagramPacket receivePacket = new DatagramPacket( data, data.length ); socket.receive( receivePacket ); // wait for packet
// display information from received packet displayMessage( "\nPacket received:" + "\nFrom host: " + receivePacket.getAddress() + "\nHost port: " + receivePacket.getPort() + "\nLength: " + receivePacket.getLength() + "\nContaining:\n\t" + new String( receivePacket.getData(), 0, receivePacket.getLength() ) ); sendPacketToClient( receivePacket ); // send packet to client }// process problems manipulating packet catch( IOException ioException ) { displayMessage( ioException.toString() + "\n" ); ioException.printStackTrace(); } } // end while } // end method waitForPackets // echo packet to client privatevoid sendPacketToClient( DatagramPacket receivePacket ) throws IOException {
displayMessage( "\n\nEcho data to client..." ); // create packet to send DatagramPacket sendPacket = new DatagramPacket( receivePacket.getData(), receivePacket.getLength(), receivePacket.getAddress(), receivePacket.getPort() ); socket.send( sendPacket ); // send packet displayMessage( "Packet sent\n" ); } // utility method called from other threads to manipulate // displayArea in the event-dispatch thread privatevoid displayMessage( final String messageToDisplay ) { // display message from event-dispatch thread of execution SwingUtilities.invokeLater( new Runnable() { // inner class to ensure GUI updates properly publicvoid run() // updates displayArea { displayArea.append( messageToDisplay ); displayArea.setCaretPosition( displayArea.getText().length() ); }
} // end inner class ); // end call to SwingUtilities.invokeLater } publicstaticvoid main( String args[] ) { Server application = new Server(); application.setDefaultCloseOperation( JFrame.EXIT_ON_CLOSE ); application.waitForPackets(); } } // end class Server
Access resources via URLs • What Is a URL ? • an acronym for Uniform Resource Locator • is a reference (an address) to a resource on the Internet. • Format: • scheme : [// [host [:port]]][ path [reference]] • EXs: • http://www.cs.nccu.edu.tw • http://xml.cs.nccu.edu.tw/Courses/java2002/index.html#loc2 • ftp://java.sun.com/pub/ • http://java.sun.com/servlet/app1?user=chen+passwd=**** • file:///D:/chencc/java2002/index.html
Creating a URL • Direct from URL address • String j2k = “http://xml.cs.nccu.edu.tw/Courses/java2000”; • URL j2000 = new URL(j2k); // or • URL j2000 = new URL • (“http”, “xml.cs.nccu.edu.tw”, “Courses/java2000”); • Relative to another URL address • String coursesLoc = “http://xml.cs.nccu.edu.tw/Courses/index.html” • URL coursesURL = new URL(coursesLoc); • URL j2000 = new URL(coursesURL, “java2002/index.html”); • Constructor Summary • URL(String spec) • URL(String scheme, String host [, int port] , String file [, URLStreamHandler h]) • URL(URL baseURL, String relativeURL [,URLStreamHandler] ) • possible exception: MalformedURLException
Parsing a URL • getProtocol • Returns the protocol identifier component of the URL. • getHost • Returns the host name component of the URL. • getPort • Returns the port number component of the URL. • The getPort method returns an integer that is the port number. • If the port is not set, getPort returns -1. • getFile • Returns the filename component of the URL. • getRef • Returns the reference component of the URL.
Example 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/index.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()); } } • Here's the output displayed by the program: protocol = http host = java.sun.com filename = /docs/books/tutorial/index.html port = 80 ref = DOWNLOADING
Reading Directly from a URL • InputStream openStream();// return a stream for reading • EX: URL yahoo = new URL("http://www.yahoo.com/"); BufferedReader in = new BufferedReader( new InputStreamReader( yahoo.openStream()) ); String inputLine; while ((inputLine = in.readLine()) != null) System.out.println(inputLine); in.close();
Connecting to a URL • URLConnection openConnection() throws IOException; • EX: try { URL yahoo = new URL("http://www.yahoo.com/"); URLConnection yahooConnection = yahoo.openConnection(); … } catch (MalformedURLException e) { // new URL() failed . . . } catch (IOException e) { // openConnection() failed . . . }