Java Programming The Language of Now & the Future Clients and Servers including Internet connectivity, I/O and JDBC John Morris and Peter Jones Department of Electrical and Electronic Engineering, University of Western Australia John Morris Peter Jones
Sockets Sockets are the “endpoints” of Internet connections Socket constructors require Internet addresses Socket( String host, int port ) throws UnknownHostException, IOException; Socket(InetAddress address, int port) throws IOException;... and a host of other alternatives, see the API documentation! Note: these constructors throw exceptions Use them in a try { } catch.. block Machine A Machine B Ports 00 nnn Internet
Sockets Note: these constructors throw exceptions Use them in a try { } catch.. Block Note: UnknownHostException is a subclass of IOException catch( IOException e ) alone would suffice String name = new String(“ciips.ee.uwa.edu.au”); try { Socket t = new Socket( name, 80 );... } catch( UnknownHostException e ) { System.out.println(“Unknown host:” + name ); } catch( IOException e ) {... }
Aside: Datagrams,... Use a DatagramSocket Constructor DatagramSocket( int port ) throws IOException ; creates a datagram socket on port Methods void receive( DatagramPacket p ) throws IOException ; void send( DatagramPacket p ) throws IOException ; DatagramPacket Constructor DatagramPacket( byte[] buf, int length, InetAddress add, int port ); creates a packet to be sent to port at add Methods byte[] getData(); void setData( byte[] buf ); InetAddress getAddress();
Datagrams,... Use a DatagramSocket Constructor DatagramSocket( int port ) throws IOException ; creates a datagram socket on port Methods void receive( DatagramPacket p ) throws IOException ; void send( DatagramPacket p ) throws IOException ; DatagramPacket Constructor DatagramPacket( byte[] buf, int length, InetAddress add, int port ); creates a packet to be sent to port at add Methods byte[] getData(); void setData( byte[] buf ); InetAddress getAddress(); Note: byte[] not char[]... more later!
Multicast sockets... Messages to multiple hosts Use a MulticastSocket Constructor MulticastSocket( int port ) throws IOException; creates a datagram socket bound to port Methods void receive( DatagramPacket p ) throws IOException ; void send( DatagramPacket p ) throws IOException; void joinGroup( InetAddress mcastaddr ) throws IOException ; void leaveGroup( InetAddress mcastaddr ) throws IOException ; Hosts can join and leave multicast groups Security feature: An applet is not allowed to use a multicast socket Inherited from DatagramSocket
static final int lut_port = 3062; String name = new String(“ciips.ee.uwa.edu.au”); static final String query = “?”; try { Socket server = new Socket( name, lut_port ); DataInputStream input = new DataInputStream( server.getInputStream() ); PrintStream output = new PrintStream( server.getOutputStream() ); do { output.println( query ); String resp = input.readLine(); System.out.println( name + “ response: “ + resp ); } while ( !( resp.equal( quit_string ) ) ); server.close(); } catch( UnknownHostException e ) { System.out.println(“Unknown host:” + name ); } catch( IOException e ) {... } Talking to a server
static final int lut_port = 3062; String name = new String(“ciips.ee.uwa.edu.au”); static final String query = “?”; try { Socket server = new Socket( name, lut_port ); DataInputStream input = new DataInputStream( server.getInputStream() ); PrintStream output = new PrintStream( server.getOutputStream() ); do { output.println( query ); String resp = input.readLine(); System.out.println( name + “ response: “ + resp ); } while ( !( resp.equal( quit_string ) ) ); server.close(); } catch( UnknownHostException e ) { System.out.println(“Unknown host:” + name ); } catch( IOException e ) {... } Talking to a server Socket (and almost all the rest) throws an exception, so put it all in a try { } block Once the Socket has been created, create input and output streams on it DataInputStream DataOutputStream PrintStream Just part of the stream zoo - there are 55 more!
static final int lut_port = 3062; String name = new String(“ciips.ee.uwa.edu.au”); static final String query = “?”; try { Socket server = new Socket( name, lut_port ); DataInputStream input = new DataInputStream( server.getInputStream() ); PrintStream output = new PrintStream( server.getOutputStream() ); do { output.println( query ); String resp = input.readLine(); System.out.println( name + “ response: “ + resp ); } while ( !( resp.equal( quit_string ) ) ); server.close(); } catch( UnknownHostException e ) { System.out.println(“Unknown host:” + name ); } catch( IOException e ) {... } Talking to a server Now use methods on the streams just like any other I/O device println on PrintStream readLine on DataInputStream
static final int lut_port = 3062; String name = new String(“ciips.ee.uwa.edu.au”); static final String query = “?”; try { Socket server = new Socket( name, lut_port ); DataInputStream input = new DataInputStream( server.getInputStream() ); PrintStream output = new PrintStream( server.getOutputStream() ); do { output.println( query ); String resp = input.readLine(); System.out.println( name + “ response: “ + resp ); } while ( !( resp.equal( quit_string ) ) ); server.close(); } catch( UnknownHostException e ) { System.out.println(“Unknown host:” + name ); } catch( IOException e ) {... } Talking to a server Finally add some code to handle exceptions! Choices (Java usually gives you plenty ) ¬ Separate catch blocks for different types One “catch all” ( IOException ) try { } catch { } for each method call ¯ Throw the exception from here
static final int lut_port = 3062; String name = new String(“ciips.ee.uwa.edu.au”); static final String query = “?”; try { Socket server = new Socket( name, lut_port ); } catch( UnknownHostException e ) { System.out.println(“Unknown host:” + name ); return error_flag ; } catch( IOException e ) { /* process other errors.... */ return error_flag ; } try { DataInputStream input = new DataInputStream( server.getInputStream() ); PrintStream output = new PrintStream( server.getOutputStream() ); } catch( IOException e ) { System.out.println(“Cant form streams”); return error_flag ; } do { /* do some real work... */ Talking to a server - variant 1 Exception Choices (Java usually gives you plenty ) try { } catch { } for each method call ¯ Throw the exception from here try { } catch { } around each exception throwing call
public String ServerResp( String query ) throws IOException { static final int lut_port = 3062; String name = new String(“ciips.ee.uwa.edu.au”); Socket server = new Socket( name, lut_port ); DataInputStream input = new DataInputStream( server.getInputStream() ); PrintStream output = new PrintStream( server.getOutputStream() ); output.println( query ); String resp = input.readLine(); server.close(); return resp; } Talking to a server - variant 2 Exception Choices (Java usually gives you plenty ) try { } catch { } for each method call ¯ Throw the exception from here This method throws any exceptions up a level
static final int lut_port = 3062; static final int queue_len = 10; try { Socket server = new ServerSocket( lut_port, queue_len ); } catch( IOException e ) { System.out.println(“Can’t establish server on port “ + lut_port ); } while( true ) { // The server never dies! // Wait for a connection attempt try { Socket s = server.accept(); PrintStream ps = new PrintStream( s.getOutputStream() ); DataInputStream in = new DataInputStream( s.getInputStream() ); while( true ) { String q = in.readLine(); if ( q.equal( “?” ) ) ps.println( “Hello” ); else if ( q.equal( “quit” ) ) break; else ps.println( “??” ); } s.close(); // Close this connection } catch ( IOException e ) { /* Do something about it! */ } } Simple Server
static final int lut_port = 3062; static final int queue_len = 10; try { Socket server = new ServerSocket( lut_port, queue_len ); } catch( IOException e ) { System.out.println(“Can’t establish server on port “ + lut_port ); } while( true ) { // The server never dies! // Wait for a connection attemtp try { Socket s = server.accept(); PrintStream ps = new PrintStream( s.getOutputStream() ); DataInputStream in = new DataInputStream( s.getInputStream() ); while( true ) { String q = in.readLine(); if ( q.equal( “?” ) ) ps.println( “Hello” ); else if ( q.equal( “quit” ) ) break; else ps.println( “??” ); } s.close(); // Close this connection } catch ( IOException e ) { /* Do something about it! */ } } Simple Server Set up a ServerSocket - basically just a socket with an accept method Servers usually live forever!! The code will block here until a client attempts a connection
static final int lut_port = 3062; static final int queue_len = 10; try { Socket server = new ServerSocket( lut_port, queue_len ); } catch( IOException e ) { System.out.println(“Can’t establish server on port “ + lut_port ); } while( true ) { // The server never dies! // Wait for a connection attemtp try { Socket s = server.accept(); PrintStream ps = new PrintStream( s.getOutputStream() ); DataInputStream in = new DataInputStream( s.getInputStream() ); while( true ) { String q = in.readLine(); if ( q.equal( “?” ) ) ps.println( “Hello” ); else if ( q.equal( “quit” ) ) break; else ps.println( “??” ); } s.close(); // Close this connection } catch ( IOException e ) { /* Do something about it! */ } } Simple Server Now we just ¬ create the input & output streams read and write to them ® close the connection when we’re finished
static final int lut_port = 3062; static final int queue_len = 10; try { Socket server = new ServerSocket( lut_port, queue_len ); } catch( IOException e ) { System.out.println(“Can’t establish server on port “ + lut_port ); } while( true ) { // The server never dies! // Wait for a connection attemtp try { Socket s = server.accept(); PrintStream ps = new PrintStream( s.getOutputStream() ); DataInputStream in = new DataInputStream( s.getInputStream() ); while( true ) { String q = in.readLine(); if ( q.equal( “?” ) ) ps.println( “Hello” ); else if ( q.equal( “quit” ) ) break; else ps.println( “??” ); } s.close(); // Close this connection } catch ( IOException e ) { /* Do something about it! */ } } Simple Server But... This server blocks whilst one user is using it! A second client can’t connect ‘til the first one finishes! Solution... A thread for each client
static final int lut_port = 3062; static final int queue_len = 10; try { Socket server = new ServerSocket( lut_port, queue_len ); } catch( IOException e ) { System.out.println(“Can’t establish server on port “ + lut_port ); } while( true ) { // The server never dies! // Wait for a connection attempt try { Socket s = server.accept(); // This thread will do the talking ClientHandler ch = new ClientHandler( s ); ch.start(); } catch ( IOException e ) { /* Do something about it! */ } } Multi-threaded Server Make this parameter relevant! Number of queued requests As soon as we get a connection, spawn a handler thread to talk to the client Start the thread
class ClientHandler extends Thread { Socket s; public ClientHandler( Socket s ) { this.s = s; } public void run() { PrintStream ps = new PrintStream( s.getOutputStream() ); DataInputStream in = new DataInputStream( s.getInputStream() ); while( true ) { String q = in.readLine(); if ( q.equal( “?” ) ) ps.println( “Hello” ); else if ( q.equal( “quit” ) ) break; else ps.println( “??” ); } s.close(); // Close this connection } Multi-threaded Server - The Handler Same operational code.. Just embedded in the thread’s run method Constructor - just save a reference to the socket This class is a Thread
I/O Streams - Too much choice? There’s a bewildering array of choices... “Stream Zoo” Considering input.. InputStream å ByteArrayInputStream å FileInputStream å FilterInputStream BufferedInputStream å DataInputStream å DataInput å InflaterInputStream åGZIPInputStream åZipInputStream å... 3 more! PipedInputStream å... 3 more! Matching Output classes also!
I/O Streams - Too much choice?... and the Reader classes! Characters (16 bits!) rather than bytes Reader å BufferedReader å LineNumberReader å CharArrayReader å FilterReader PushbackReader å InputStreamReader å FileReader å PipedReader å StringReader Matching Writer classes also!
Writing Objects to Streams ObjectOutputStream Enables writing of serialized objects Serializable objects implement the java.io.Serializable interface private void writeObject( ObjectOutputStream out ) throws IOException; private void readObject( ObjectInputStream in ) throws IOException, ClassNotFoundException; ClassNotFoundException? A remote program could send you an object that you don’t know about.... and therefore don’t know how to de-serialize!
Bytes and characters in Java Java has Primitive types byte char Classes Byte Character Class Byte has a single attribute of type byte It’s just a class “wrapper” for a byte Class Character... Characters are Unicode characters For the full tables, see ftp://ftp.unicode.org/Public Character methods isDigit, isLetter, isLowerCase,... Full story: Gosling, Joy & Steele, “The Java Language Specification”
Bytes and characters in Java Class Character... Characters are Unicode characters Main trap... “char” files created by other programs, eg C, C++ Files created by text editors... but Windows “NotePad” often creates Unicode files for you! Suggestion Use byte / Byte if the file, stream,... may be generated/read by any other language
URLs Not surprisingly, Java provides good support for URLs URL class Constructors URL( String spec ); URL( String protocol, String host, int port, String file ); URL( String protocol, String host, String file ); Methods Object getContent(); Retrieve the whole file URLConnection openConnection(); Used when URLConnection subclasses, eg HttpURLConnection, JarURLConnection exist InputStream openStream() ;
SQL databases JDBC provides a bridge to an Open Database Connectivity (ODBC) interface to a specific database Getting started import java.sql.*; Load the bridge.. Class.forName( “sun.jdbc.odbc.JdbcOdbcDriver” ); Connect to a database Connection c = DriverManager.getConnection( String URL, String username, String passwd ); Create an SQL statement Statement s = c.createStatement(); Execute a statement s.execute( String sql_statement );
SQL databases JDBC Results from a query ResultSet res = s.executeQuery( String s ); Goto the first row... res.next(); Extract data String name = res.getString( String col_name ); int value = res.getInt( String col_name );... and, of course, several pages more! Examing the table returned ResultSetMetaData m = res.getMetaData(); Information about the table int columns = m.getColumnCount(); String label = m.getColumnLabel( int col_no ); Columns number from 1! String ctype = m.getColumnType( int col_no );... and, of course, 19 more!