650 likes | 761 Views
This lecture provides an overview of distributed computing in Java, covering key concepts such as network programming, JDBC, servlets, RMI, and other advanced technologies like CORBA and Enterprise JavaBeans (EJB). It delves into the complexities historically associated with network programming, highlighting how Java's I/O stream library simplifies TCP/IP communication. Key topics include the differences between TCP and UDP protocols, client-server architecture, and unique machine identification using IP addresses. The session concludes with practical examples of server-client implementation and socket connections.
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)? } } }
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
Datagrams • You make your own packets and write the address on the outside, send it • Based on packet contents, recipient decides 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
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
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 openConnectino() 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 . . . }
Reading from and Writing to a URLConnection • Reading from a URLConnection // like direct reading from URL using openStream() URL yahoo = new URL("http://www.yahoo.com/"); URLConnection yc = yahoo.openConnection(); BufferedReader in = new BufferedReader( new InputStreamReader( yc.getInputStream())); String inputLine; while ((inputLine = in.readLine()) != null) System.out.println(inputLine); in.close();
Writing to a URLConnection • procedures • 1.Create a URL. • 2.Open a connection to the URL. • 3.Set output capability on the URLConnection. • 4.Get an output stream from the connection. This output stream is connected to the standard input stream of the cgi-bin script on the server. • 5.Write to the output stream. • 6.Close the output stream.
String stringToReverse = URLEncoder.encode(args[0]); URL url = new URL("http://java.sun.com/cgi-bin/backwards"); URLConnection connection = url.openConnection(); connection.setDoOutput(true); PrintWriter out = new PrintWriter( connection.getOutputStream()); out.println("string=" + stringToReverse); out.close(); BufferedReader in = new BufferedReader( new InputStreamReader( connection.getInputStream())); String inputLine; while ((inputLine = in.readLine()) != null) System.out.println(inputLine); in.close();
JDBC • Java DataBase Connectivity • Allows you to write SQL without worrying about what brand of database you’re connecting to • Provides a simple interface for database programming
JDBC database URL • A string used to identify data source ( and parameters) • The format: • jdbc: <subprotocol> : <otherStuff> • “jdbc” means using JDBC • <subprotocol>: the name of the driver or the name of a database connectivity mechanism. • <otherStuff> : the database identifier. This varies with the database driver used. • the first subprotocol available is the “jdbc-odbc bridge,” specified by “odbc” • EX: String dbUrl = "jdbc:odbc://whitehouse.gov:5000/CATS;PWD=Hillary";
//: c15:Lookup.java // Looks up email addresses in a local database using JDBC import java.sql.*; public class Lookup { public static void main(String args[]) { String dbUrl = "jdbc:odbc:people"; String user = ""; String password = ""; try { // Load the driver (registers itself) Class.forName( "sun.jdbc.odbc.JdbcOdbcDriver"); Connection c = DriverManager.getConnection ( dbUrl, user, password); Statement s = c.createStatement();
// SQL code: ResultSet r = s.executeQuery( "SELECT FIRST, LAST, EMAIL FROM people.csv people " + "WHERE (LAST='" + args[0] + "') " + " AND (EMAIL Is Not Null) " + "ORDER BY FIRST"); while(r.next()) { // Capitalization doesn't matter: System.out.println( r.getString("Last") + ", " + r.getString("fIRST") + ": " + r.getString("EMAIL") ); } } catch(Exception e) { e.printStackTrace(); } } }
Servlets • Servlets are to servers what applets are to browsers • Servlet API (a standard Java extension) is truly cross-platform • Substitute for CGI scripts • Easier to write, faster to run • Not tied to any platform-specific API • Better than CGI scripts • Stay resident: speed, persistent • information • Multithreading locks prevent collisions • Session tracking built in
Running servlets locally • Download the Tomcat implementation of Java Servlets and JSPs • http://jakarta.apache.org • Official Servlet/JSP distribution • Free! Part of Apache project • Will eventually be integrated into Apache to make it a true application server • Execute Tomcat.bat start
Works with both GET & POST import javax.servlet.*; import javax.servlet.http.*; import java.io.*; public class ServletsRule extends HttpServlet { int i = 0; // Servlet "persistence" public void service(HttpServletRequest req, HttpServletResponse res) throws IOException { PrintWriter out = res.getWriter(); out.print("<HEAD><TITLE>"); out.print("A server-side strategy"); out.print("</TITLE></HEAD><BODY>"); out.print("<h1>Servlets Rule! " + i++); out.print("</h1></BODY>"); out.close(); } }
Easy to get HTML form data // Dumps the name-value pairs of any HTML form import javax.servlet.*; import javax.servlet.http.*; import java.io.*; import java.util.*; public class EchoForm extends HttpServlet { public void doGet(HttpServletRequest req, HttpServletResponse res) throws IOException { res.setContentType("text/html"); PrintWriter out = res.getWriter(); out.print("<h1>Your form contained:</h1>"); Enumeration flds = req.getParameterNames(); while(flds.hasMoreElements()) { String field = (String)flds.nextElement(); String value = req.getParameter(field); out.print(field + " = " + value + "<br>"); } out.close(); }
public void doPost(HttpServletRequest req, HttpServletResponse res) throws IOException { doGet(req, res); } }
One servlet, thread-per-request import javax.servlet.*; import javax.servlet.http.*; import java.io.*; public class ThreadServlet extends HttpServlet { int i; public void service(HttpServletRequest req, HttpServletResponse res) throws IOException { res.setContentType("text/html"); PrintWriter out = res.getWriter(); synchronized( this) { try { Thread.currentThread().sleep(5000); } catch( InterruptedException e) {} } out.print("<h1>Finished " + i++ + "</h1>"); out.close(); } }
Java Server Pages (JSPs) • Servlets still require web pages • Why not combine only the essential servlet code with the HTML code? • Why not minimize the Java code you have to write? • Inspired by ASPs but much nicer • The easiest way to experiment with servlet properties • You can include special servlets, calls to Java libraries, etc.
Java Server Web Dev Kit • From java.sun.com, exceptionally easy to install and run • All you do is put .jsp files in the appropriate directory, point your web browser at them • JSP is automatically built, compiled and loaded on the first call, just like a servlet
Most code is built for you <html><body> <H1>The time in seconds is: <%= System.currentTimeMillis()/1000 %> </H1> </body></html> • Plenty of Java code is produced, +HTML • The ‘<%=’ coerces the resulting expression to a String • Code automatically rebuilt & recompiled when JSP source file changes
Basic JSP operations <%-- This JSP comment will not appear in the generated html --%> <%-- This is a JSP directive: --%> <%@ page import="java.util.*" %> <%-- These are declarations: --%> <%! long loadTime= System.currentTimeMillis(); Date loadDate = new Date(); int hitCount = 0; %> <html><body> <%-- The next several lines are the result of a JSP expression inserted in the generated html; the '=' indicates a JSP expression--%> <H1>This page was loaded at <%= loadDate %> </H1>