Client / Server Programming in Java Client / Server in Java • Primary communications is through sockets. – (Web type access also available through URL class) • Browser security limits the access that a program can have when run as an applet. (Typically limited to opening a socket back on its host machine). So.. applets are typically clients. • “Default” socket is stream (TCP). • Socket classes implemented in java.net package cs423-cotter 2 Basic Sockets Classes • • • • • • • • Socket ServerSocket SocketAddress InetAddress Datagram Socket Datagram Packet Multicast Socket URL cs423-cotter 3 Socket Client/Server in Java • Typically client is applet, but can be command line or graphical application • Server is written as java application or even in some other language (c, c++, etc.). • Where client access is through the Web , the server must be running on the web server machine. cs423-cotter 4 TCPecho / TCPechos C:\data\cs423_sp12\java\TCPechos\dist>java -jar TCPechos.jar 3456 Serv: Initializing to port 3456 Serv: Waiting for a connection... Serv: Receved a connection *---------------* Srx: Connected to: /127.0.0.1:12405 We just received: (14) This is a test We just received: (20) This is another test Srvx disconnected from /127.0.0.1 *---------------------* Serv: Waiting for a connection... C:\data\cs423_sp12\java\TCPechos\dist> C:\data\cs423_sp12\java\basicTCPecho\dist>java -jar basicTCPecho.jar localhost 3456 Enter text to read: This is a test Client: Rcvd from server: This is a test (14 bytes) Enter text to read: This is another test Client: Rcvd from server: This is another test (20 bytes) Enter text to read: bye C:\data\cs423_sp12\java\basicTCPecho\dist> cs423-cotter 5 Iterative TCP echo Server package tcpechos; import java.net.*; import java.io.*; public class TCPechos { public static void main(String[] args) { Socket sock; ServerSocket ssock; InputStream isIn; PrintStream psOut; int iNumRead, numPort; String sendMsg, port = "5678"; byte abIn[] = new byte[1024]; cs423-cotter 6 Iterative TCP echo Server // Handle command line arguments switch (args.length) { case 1: port = args[0]; break; case 0: break; default: System.out.println("Illegal number of arguments."); System.exit(1); } numPort = Integer.parseInt(port); //port number must be an int for Socket System.out.println ("Serv: Initializing to port " + numPort); cs423-cotter 7 Iterative TCP echo Server try { // Create the server socket and bind it to our port ssock = new ServerSocket (numPort); while (true) { // Wait for a client request System.out.println ("Serv: Waiting for a connection..."); sock = ssock.accept(); // We got a connection request! Print out info and start talking System.out.println ("Serv: Receved a connection"); System.out.println ("*---------------*"); System.out.println ("Srx: Connected to: " +sock.getInetAddress() + ":" +sock.getPort()); psOut = new PrintStream (sock.getOutputStream()); isIn = sock.getInputStream(); iNumRead = 0; cs423-cotter 8 Iterative TCP echo Server while (iNumRead >= 0) { //Keep reading as long as we get data iNumRead = isIn.read(abIn, 0, 1024); if (iNumRead < 0) break; sendMsg = new String(abIn,0,iNumRead); System.out.println("We just received: (" +iNumRead + ") " + sendMsg); //Note that the received message includes '\n' and //we add one of our own with println psOut.print(sendMsg); iNumRead = 0; } sock.close(); System.out.println ("Srvx disconnected from " + sock.getInetAddress()); System.out.println ("*---------------------*"); } //end of while } //end of try catch (Exception e) { System.err.println (":Serv: Exception in main: " + e); } } //end of main() } //end of TCPechos cs423-cotter 9 Basic TCP echo Client import java.io.*; import java.util.*; public class BasicTCPecho { public static void main(String[] args) { // TODO code application logic here Socket sock; String sIn, host = "localhost", port = "5678"; //default host and port InputStream isIn; PrintStream psOut; byte abIn[] = new byte[1024]; int iNumRead, numPort; Scanner input; cs423-cotter 10 Basic TCP echo Client // Deal with any command line arguments switch (args.length) { case 2: port = args[1]; case 1: host = args[0]; break; case 0: break; default: System.out.println("Illegal number of arguments."); System.exit(1); } numPort = Integer.parseInt(port); //port number must be an int for Socket cs423-cotter 11 Basic TCP echo Client try { sock = new Socket(host, numPort); isIn = sock.getInputStream(); psOut = new PrintStream(sock.getOutputStream()); input = new Scanner (System.in); while (true) { //First we get some text from the user. System.out.print("Enter text to read: "); sIn = input.nextLine(); //If we typed “bye”, then exit client if (sIn.equals("bye")) { sock.close(); break; } cs423-cotter 12 Basic TCP echo Client //next we send that to the server psOut.print(sIn); //Now, wait for something to come back... iNumRead = isIn.read(abIn,0,1024); if (iNumRead < 0) { break; //connection has been closed } String str = new String(abIn,0,iNumRead); System.out.println("Client: Rcvd from server: " + str + " (" + iNumRead + " bytes)"); } sock.close(); } catch (Exception e) { System.out.println("Client: exception " + e); } }//end of main }//end of class cs423-cotter 13 Threads in Java • Multithreading built into Java language • Thread (String threadName) • Thread ( ) (named “Thread- + number”)) • Thread States – – – – – – – born ready running waiting sleeping dead blocked cs423-cotter 14 Thread State Diagram born ready running waiting sleeping dead cs423-cotter blocked 15 Thread Priorities • • • • • • • Priority range 1 to 10 Thread.MIN_PRIORITY = 1; Thread.MAX_PRIORITY = 10; Thread.NORM_PRIORITY = 5; Thread.setPriority (int); Thread.getPriority( ); Threads processed in priority order, with roundrobin processing within a priority • Starvation possible cs423-cotter 16 Thread class public class Thread extends Object implements Runnable { Thread ( ); Thread (Runnable object); run ( ); start ( ); getPriority ( ); sleep ( ); wait ( ); notify ( ); .... ; cs423-cotter 17 Implementing Threads (1) Subclassing the Thread class class MyNuThread extends Thread { private data ....; public MyNuThread ( ) { do constructor stuff here; } public void run( ) { here’s where work is done } } cs423-cotter 18 Using Threads (1) MyNuThread thread1 = new MyNuThread ( ); thread1.start( ); cs423-cotter 19 Implementing Threads (2) Make an existing class runnable class ServerExtension implements Runnable { private data....; public ServerExtension( ) { do constructor stuff here; } public void run( ) { do work stuff here } } cs423-cotter 20 Using extended classes ServerExtension servx = new ServerExtension( ); Thread thServx = new Thread (servx); thServx.start(); cs423-cotter 21 Multi-threaded server Output C:\data\cs423_sp12\java>java -jar TCPechod.jar Serv: Initializing to port 3456 Serv: Waiting for a connection... Serv: Received connection 1 Serv: Waiting for a connection... *---------------* Srx: Connected to: /127.0.0.1:47871 We just received: (21) This is from client 1 Serv: Received connection 2 Serv: Waiting for a connection... *---------------* Srx: Connected to: /127.0.0.1:47872 We just received: (21) This is from client 2 We just received: (29) This is another from client 1 We just received: (22) We're back to client 2 Srvx disconnected from /127.0.0.1 *---------------------* Srvx disconnected from /127.0.0.1 *---------------------* Srvx disconnected from /127.0.0.1 *---------------------* Srvx disconnected from /127.0.0.1 *---------------------* C:\data\cs423_sp12\java\basicTCPecho\dist>java -jar basicTCPecho.jar localhost 3456 Enter text to read: This is from client 1 Client: Rcvd from server: This is from client 1 (21 bytes) Enter text to read: This is another from client 1 Client: Rcvd from server: This is another from client 1 (29 bytes) Enter text to read: bye C:\data\cs423_sp12\java\basicTCPecho\dist>java -jar basicTCPecho.jar localhost 3456 Enter text to read: This is from client 2 Client: Rcvd from server: This is from client 2 (21 bytes) Enter text to read: We're back to client 2 Client: Rcvd from server: We're back to client 2 (22 bytes) Enter text to read: bye C:\data\cs423_sp12\java\basicTCPecho\dist cs423-cotter 22 Multi-threaded TCPecho Server package tcpechod; import java.net.*; import java.io.*; public class TCPechod { public static int counter = 0; public static void main(String[] args) { Socket sock; ServerSocket ssock; Thread thServx; ServerExtension servx; System.out.println ("Serv: Initializing to port 3456"); cs423-cotter 23 Multi-threaded TCPecho Server try { ssock = new ServerSocket (3456); while (true) { System.out.println ("Serv: Waiting for a connection..."); sock = ssock.accept(); counter++; System.out.println ("Serv: Received connection " + counter); servx = new ServerExtension(sock); String name = Integer.toString(counter); thServx = new Thread (servx, name); thServx.start(); } } catch (Exception e) { System.err.println (":Serv: lException in main: " + e); } } } cs423-cotter 24 Multi-threaded TCPecho Server class ServerExtension implements Runnable { private Socket sock; private InputStream isIn; private PrintStream psOut; private String count; public ServerExtension (Socket s) { sock = s; count = Integer.toString(TCPechod.counter); } public void run () { int iNumRead; String sendMsg; byte abIn[] = new byte[1024]; System.out.println ("*---------------*"); System.out.println("Srx: Connected to: " + sock.getInetAddress() + ":“ +sock.getPort()); cs423-cotter 25 Multi-threaded TCPecho Server try { psOut = new PrintStream (sock.getOutputStream()); isIn = sock.getInputStream(); iNumRead = 0; while (iNumRead >= 0) { iNumRead = isIn.read(abIn, 0, 1024); if (iNumRead < 0) break; sendMsg = new String(abIn,0,iNumRead); System.out.println("We just received: (" +iNumRead + ") " + sendMsg); //Note that the received message includes '\n' and //we add one of our own with println psOut.print(sendMsg); iNumRead = 0; } // end of while cs423-cotter 26 Multi-threaded TCPecho Server sock.close(); System.out.println ("Srvx disconnected from " + sock.getInetAddress()); System.out.println ("*---------------------*"); }//end of try catch (Exception e) { System.err.println (":Serv: Exception in main: " + e); } System.out.println ("Srvx disconnected from " + sock.getInetAddress()); System.out.println ("*---------------------*"); } } cs423-cotter 27 NetBeans Graphical Client cs423-cotter 28 NetBeans Project • TCPecho – build – dist • TCPecho.jar – nbproject – src • META-INF • tcpecho – – – – – – resources TCPechoAboutBox.form TCPechoAboutBox.java TCPechoApp.java TCPechoView.form TCPechoView.java cs423-cotter 29 NetBeans Project Structure • TCPechoApp.java – Basic application shell. – Application class with main() method – startup() method creates and shows TCPechoView • TCPechoView.java – In NetBeans 7.0, GUI built drag-and-drop. Code generated from objects created. – Actions added to buttons by identifying ActionPerformed methods and then adding in actions to that method. • TCPechoAboutBox.java – Automatically constructed dialog box. cs423-cotter 30 NetBeans Project Layout cs423-cotter 31 UDP Temperature Server import java.net.*; import java.io.*; class TempServer { public static void main (String argv[]) { DatagramSocket sock; DatagramPacket sendPacket, recvPacket; int tempF; int tempC; try { sock = new DatagramSocket (5678); System.out.println ("Serv: Bound to port 5678"); cs423-cotter 32 UDP Temperature Server while (true) { System.out.println ("Serv: Waiting for a request..."); byte data[] = new byte[25]; recvPacket = new DatagramPacket (data, data.length); sock.receive(recvPacket); System.out.println ("Serv: Received a packet..."); String tempFs = new String(recvPacket.getData(),0,recvPacket.getLength()); tempF = Integer.parseInt(tempFs); tempC = (int)(5*(tempF -32)/9); String tempCs = Integer.toString(tempC); data = tempCs.getBytes(); sendPacket = new DatagramPacket (data, data.length, recvPacket.getAddress(), recvPacket.getPort()); sock.send(sendPacket); System.out.println("We got a temp of " + tempFs + " and returned " + tempCs); } cs423-cotter 33 UDP Temperature Server } catch (Exception e) { System.err.println (":Serv: lException in main: " + e); } }//end of main }//end of class cs423-cotter 34 Graphical UDP Temperature Client cs423-cotter 35 Graphical UDP Temperature Client import java.awt.*, javax.swing.* java.awt.event.* java.net.* java.io.*; public class udpTemp extends JFrame implements WindowListener, ActionListener{ udpTemp() //Build graphical layout public void actionPerformed(ActionEvent evt) // handle events public static void main (String[] args) // start the program public void windowClosing(WindowEvent e) //Handle Window events private TextField portField; : private DatagramSocket sock; }//end of class cs423-cotter 36 UDP Temp Client - constructor udpTemp() { setTitle("UDP Temp Demo"); setSize(400,300); addWindowListener (this); //setBackground(Color.blue); bgColor = new Color(16, 134, 197); setLayout(new BorderLayout()); Panel p = new Panel(); p.setBackground(bgColor); p.setLayout(new FlowLayout()); Button convertButton = new Button("Convert"); convertButton.addActionListener(this); p.add(convertButton); hostField = new TextField("localhost", 25); p.add(hostField); cs423-cotter 37 UDP Temp Client - constructor portField = new TextField("5678", 6); p.add(portField); add("North",p); Panel p2 = new Panel(); p2.setLayout(new FlowLayout()); p2.setBackground(bgColor); tempFField = new TextField("75", 4); p2.add(tempFField); tempCField = new TextField("", 4); p2.add(tempCField); add("Center",p2); Panel p3 = new Panel(); p3.setBackground(bgColor); resultField = new TextArea("results...",8,40); p3.add(resultField); add("South",p3); }//end of constructor. cs423-cotter 38 UDP Temp Client - actionPerformed public void actionPerformed(ActionEvent evt) { InetAddress ia = null; InputStream isIn; PrintStream psOut; byte abIn[] = new byte[1024]; byte abOut[] = new byte[1024]; int iNumRead, iNumSent; if (evt.getActionCommand().equals("Convert")) { int portNumber = (new Integer(portField.getText())).intValue(); String s1 = "The port number is " + portNumber + "\n"; resultField.setText(s1); cs423-cotter 39 UDP Temp Client - actionPerformed try { String hostName = hostField.getText(); s1 = "The host is " + hostName + "\n"; resultField.append(s1); ia = InetAddress.getByName(hostName); sock = new DatagramSocket (); String tempF = tempFField.getText(); s1 = "The temperature is " + tempF + "\n"; resultField.append(s1); abOut = tempF.getBytes(); sendPacket = new DatagramPacket (abOut, abOut.length, ia, portNumber); sock.send (sendPacket); s1 = "We just sent a packet\n"; resultField.append(s1); recvPacket = new DatagramPacket (abIn, abIn.length); sock.receive(recvPacket); String str = new String (recvPacket.getData(), 0, recvPacket.getLength()); tempCField.setText(str); cs423-cotter 40 UDP Temp Client - actionPerformed } catch (Exception exc) { System.out.println ("Clnt: Exception reading server data: " + exc); } }//end of if Convert... }//end fo ActionPerformed cs423-cotter 41 UDP Temp Client – window methods public void windowClosing(WindowEvent e) { try { String s1 = "Goodbye ..."; resultField.setText(s1); Thread.sleep(750); } catch (Exception exc) { System.out.println("Exception" + exc); } System.exit(0); } public void windowOpened(WindowEvent e) { System.out.println ("Opening Window"); } public void windowClosed(WindowEvent e) {} public void windowIconified(WindowEvent e) {} public void windowDeiconified(WindowEvent e) {} public void windowActivated(WindowEvent e) {} cs423-cotter 42 UDP Temp Client – private data private Color bgColor; private TextField portField; private TextField hostField; private TextField tempFField; private TextField tempCField; private TextArea resultField; private DatagramPacket sendPacket, recvPacket; private DatagramSocket sock; }//end of class cs423-cotter 43 Summary • Java Client / Server Introduction – Basic processes / classes • • • • Basic TCPecho Client / Server Threads in Java Multi-threaded TCPecho Server Graphical TCPecho Client – NetBeans Project • UDP Temperature Server • Graphical UDP Temperature Client cs423-cotter 44