Survey
* Your assessment is very important for improving the workof artificial intelligence, which forms the content of this project
* Your assessment is very important for improving the workof artificial intelligence, which forms the content of this project
Client/Server Distributed Systems 240-322, Semester 1, 2005-2006 11. Java Networking Objectives – describe basic networking in Java – Web page retrieval and sockets programming 240-322 Cli/Serv.: jnet/11 1 Contents 1. Networking Restrictions in Java 2. Basic Networking Classes 3. Sockets (Java Style) 4. Retrieving a Web Page – 4 different approaches 5. A Stream Socket Client/Server 240-322 Cli/Serv.: jnet/11 continued 2 6. 7. 8. 240-322 Cli/Serv.: jnet/11 A Datagram Socket Client/Server Networked Tic-Tac-Toe More Information 3 1. Networking Restrictions in Java Many browsers place networking restrictions on applets – usually communication is limited to being between your machine and the one where the applet came from There are no restrictions on Java applications or when using appletviewer 240-322 Cli/Serv.: jnet/11 4 Relaxing Security Applets can be signed with trusted certificates – a browser can be configured to relax security depending on an applet’s signature – an advanced topic 240-322 Cli/Serv.: jnet/11 5 2. Basic Networking Classes The J2SE documentation for java.net lists over 30 classes. A few of the key ones: InetAddress – the class that represents IP addresses and contains operations for manipulating them see 240-322 Cli/Serv.: jnet/11 section 2.1 continued 6 URL – used to retrieve the Web page at the given URL URLConnection – also used to retrieve a Web page – allows extra parameters to be sent to the URL e.g 240-322 Cli/Serv.: jnet/11 HTTP request headers continued 7 Socket – the client-side socket class for TCP ServerSocket – the server-side socket class for TCP DatagramSocket – allows a client or server to send/receive UDP packets 240-322 Cli/Serv.: jnet/11 8 2.1. Finding an IP Address Java’s InetAddress class makes the mapping between hostnames and IP addresses much easier than in UNIX. For details, look at the the documentation for java.net.InetAddress 240-322 Cli/Serv.: jnet/11 9 WhatIP.java import java.io.*; import java.net.*; public class WhatIP { public static void main(String args[]) throws IOException { InetAddress addr = InetAddress.getByName(args[0]); System.out.println("Inet address is "+ addr); } } 240-322 Cli/Serv.: jnet/11 10 Use 240-322 Cli/Serv.: jnet/11 Carried out from a DOS prompt on my Windows machine. 11 3. Sockets (Java Style) 1. Stream Sockets – the client/server connection exists for the entire duration of the request and answer similar to a telephone call – a connection-oriented service corresponds to TCP – Java has separate classes for client and server stream sockets (see section 5) 240-322 Cli/Serv.: jnet/11 12 2. Datagram Sockets – the client/server send messages (packets, datagrams) to each other similar to the postal service – a connectionless service corresponds to UDP – Java has classes for datagram sockets and packets (see section 6). 240-322 Cli/Serv.: jnet/11 13 3.1. Pinging ping is a DOS command, not Java. uses the ICMP protocol's ECHO_REQUEST datagram. The host’s answer is an ICMP ECHO_RESPONSE. ping 240-322 Cli/Serv.: jnet/11 14 ICMP packets can only be created via a socket of type SOCK_RAW. – but Java only supports SOCK_STREAM (TCP) and SOCK_DGRAM (UDP) sockets Our solution: use a TCP connection to the daytime service to pretend to ping – the daytime server listens at port 13 240-322 Cli/Serv.: jnet/11 15 3.2. DayPing.java JJ2, p.677 import java.io.*; import java.net.*; public class DayPing { public static void main(String args[]) throws Exception { if (args.length != 1) { System.out.println( "Usage: java DayPing <machine name>"); System.exit(0); } : 240-322 Cli/Serv.: jnet/11 16 String machine = args[0]; Socket so = new Socket(machine, 13); // daytime server listens at port 13 BufferedReader br = new BufferedReader( new InputStreamReader( so.getInputStream() ) ); System.out.println( machine + " is alive at " + br.readLine()); so.close(); } // end of main() } // end of DayPing class 240-322 Cli/Serv.: jnet/11 17 Notes converts the socket connection into a BufferedReader DayPing.java – this allows readLine() to be used for socket input Using layered streams to add I/O functionality on top of sockets is a powerful feature of Java. 240-322 Cli/Serv.: jnet/11 18 Use All the examples were tested on my Windows machine C> javac DayPing.java C> java DayPing calvin calvin is alive at Sat May 7 13:46:06 2005 C> java DayPing fourdots Exception in thread "main" java.net.ConnectException: Connection refused: no further information at java.net.PlainSocketImpl.socketConnect (Native Method) at java.net.PlainSocketImpl.doConnect... : at ping.main(DayPing.java:23) 240-322 Cli/Serv.: jnet/11 continued 19 After a wait C> java DayPing takasilla Exception in thread "main" java.net.UnknownHostException: takasilla at java.net.PlainSocketImpl. connect(Unknown Source) : at ping.main(DayPing.java:23) After a long wait C> java DayPing www.amazon.com Exception in thread "main" java.net.NoRouteToHostException: Operation timed out: connect at java.net.PlainSocketImpl. socketConnect(Native Method) : at ping.main(DayPing.java:23) 240-322 Cli/Serv.: jnet/11 20 3.3. Why Doesn't DayPing Work? The examples that don't work show three different errors: – ConnectException – UnknownHostException – NoRouteToHostException The "unknown host" exception is caused by an incorrect IP address. 240-322 Cli/Serv.: jnet/11 continued 21 The "connection" exception probably means that the server is unavailable (switched off) – this can be confirmed for a TCP service by trying to connect to it with telnet: $ telnet fourdots 13 Trying 172.30.255.4... telnet: Unable to connect to remote host: Connection refused $ executed from a different machine (fivedots) 240-322 Cli/Serv.: jnet/11 continued 22 The "no route to host" exception usually means that there is a firewall preventing the connection from being made. telnet response: A long wait, and then... $ telnet www.amazon.com 13 Trying 207.171.163.90... telnet: Unable to connect to remote host: Connection timed out $ tried on (fivedots) 240-322 Cli/Serv.: jnet/11 23 3.4. Firewalls at PSU (simplified) University Departmental firewall (no external socket creation; URLs allowed) calvin takasila ratree Univ. firewall (no external socket creation; URLs only through the ‘cache’ proxy) fivedots CoE Department 240-322 Cli/Serv.: jnet/11 The Internet 8080 cache 24 Ordinary users (i.e. students) cannot write socket-based programs that communicate outside PSU – this is true in any language (Java, C, etc.) But programs can retrieve Web pages (and other things) using the Java URL class – the URL request must go through PSU's cache machine 240-322 Cli/Serv.: jnet/11 25 URLs and Sockets From your data communications course, you may recall that the Web protocol, HTTP, is built on top of TCP/IP. Java's URL class uses stream sockets (TCP/IP) for its implementation – so why does it get past cache? 240-322 Cli/Serv.: jnet/11 continued 26 cache accepts socket links to valid Web servers, but also checks that the HTTP GET (or POST) message includes additional valid HTTP headers. – all of this HTTP stuff is carried out by the URL class for us 240-322 Cli/Serv.: jnet/11 27 4. Retrieving a Web Page Five ways of obtaining a Web page: – 1. use a socket, and send a GET message to the server see GetSocketPage.java – 2. use a URL object, and read the page via a stream see 240-322 Cli/Serv.: jnet/11 GetURLPage.java continued 28 – 3. use a URL object, and display the page in a browser see showPage.java – 4. display a URL in an JEditorPane see ShowURLPage.java – 5. use a HTTP URL connection, and send a GET message see 240-322 Cli/Serv.: jnet/11 Java’s networking tutorial 29 4.1. Sockets and GET GetSocketPage.java retrieves the page: http://<host name>/index.html e.g. http://fivedots.coe.psu.ac.th/index.html It prints the text of the page to stdout. 240-322 Cli/Serv.: jnet/11 continued 30 It opens a socket at port 80 for the host, which is the usually place where the Web server is listening. It sends the HTTP GET message: GET /index.html 240-322 Cli/Serv.: jnet/11 31 Diagram GET /index.html 80 GetSocketPage client 240-322 Cli/Serv.: jnet/11 Web page (as text) Web server host 32 GetSocketPage.java import java.io.*; import java.net.*; public class GetSocketPage { public static void main(String args[]) throws IOException { Socket sock = new Socket(args[0],80); : 240-322 Cli/Serv.: jnet/11 33 BufferedReader dis = new BufferedReader( new InputStreamReader( sock.getInputStream() )); PrintStream ps = new PrintStream( sock.getOutputStream() ); ps.println("GET /index.html"); String line; while ((line = dis.readLine()) != null) System.out.println(line); sock.close(); } } // end of GetSocketPage.java 240-322 Cli/Serv.: jnet/11 34 Notes converts the socket connection into a BufferedReader for input, and a PrintStream for output GetSocketPage.java – uses readLine()for socket input – uses println() for socket output 240-322 Cli/Serv.: jnet/11 35 Use C> javac GetSocketPage.java text of Web page printed to stdout C> java GetSocketPage fivedots <html> <head> <title>Un title page</title> </head> <meta http-equiv="Content-Type" content="text/html; charset=windows-874"> <style type="text/css"> : C> 240-322 Cli/Serv.: jnet/11 36 But... C> java GetSocketPage www.amazon.com Exception in thread "main" java.net.ConnectException: Connection timed out: connect at java.net.PlainSocketImpl. socketConnect(Native Method) : at GetSocketPage.main(GetSocketPage.java:18) The firewall around PSU prevents Web server access by sockets. 240-322 Cli/Serv.: jnet/11 continued 37 cache rejected the GET message to the external site since the message didn't include additional HTTP headers. These can be supplied by us, but it's easier to use the URL class. 240-322 Cli/Serv.: jnet/11 38 4.2. URL Object avoids the firewall problem with sockets by using a URL object. GetURLPage.java A URL object allows a Web page to be retrieved as a stream of text – our program prints the text to stdout. 240-322 Cli/Serv.: jnet/11 39 GetURLPage.java import java.net.*; import java.io.*; public class GetURLPage { public static void main(String args[]) { try { URL url = new URL(args[0]); BufferedReader dis = new BufferedReader( new InputStreamReader( url.openStream() )); : 240-322 Cli/Serv.: jnet/11 40 String line; while ( (line = dis.readLine()) != null ) System.out.println(line); dis.close(); } catch (Exception e) { System.out.println(e); } } } // end of GetURLPage.java 240-322 Cli/Serv.: jnet/11 41 Notes A stream for the URL object is obtained using openStream() – after that the same input stream layering technique is used as in GetSocketPage.java – there is no need to send a GET message 240-322 Cli/Serv.: jnet/11 42 Use C> javac GetURLPage.java C> java GetURLPage http://www.amazon.co.uk java.net.ConnectException: Connection timed out: connect after a long wait C> java -DproxySet=true -DproxyHost=cache.psu.ac.th -DproxyPort=8080 GetURLPage http://www.amazon.com/ <html> <head> <title>Amazon Page</title> </head> <body bgcolor=#ffffff test=#000000> <H1> : C>jnet/11 240-322 Cli/Serv.: typed on one line 43 Ordinary users can access outside PSU by using URLs, but they must route their requests via PSU cache machine. 240-322 Cli/Serv.: jnet/11 44 Batch Files for Long Commands GetURLPage.bat contains: @echo off echo Executing GetURLPage... java -DproxySet=true -DproxyHost=cache.psu.ac.th -DproxyPort=8080 GetURLPage %1 Use: c> GetURLPage http://www.amazon.co.uk : // same output as last slide 240-322 Cli/Serv.: jnet/11 45 Proxy Username/Password A further level of firewall security is to require the user to enter a username and password – called proxy authorization Java has network support for authorization – it allows a username and password to be sent by a client program to the firewall 240-322 Cli/Serv.: jnet/11 continued 46 A good tutorial: – “Jump a Proxy/Firewall and Live to Tell About it” http://www.devx.com/upload/free/features/ javapro/2000/03mar00/te0003/te0003.asp Slightly modified code is in GetThroughProxy.java at: http://fivedots.coe.psu.ac.th/ Software.coe/Cliserv/ Code%20Examples/Java%20Code/ Basic%20Networking/ 240-322 Cli/Serv.: jnet/11 47 4.3. Passing a URL to a Browser If the Java code is in an applet, then the downloaded URL can be displayed in the browser. displays a user-specified Web page in the (Opera) browser, using the ShowPage.java applet. showPage.html 240-322 Cli/Serv.: jnet/11 48 Usage The dialog box appears in front of the browser window. 240-322 Cli/Serv.: jnet/11 continued 49 Loaded Page: 240-322 Cli/Serv.: jnet/11 50 showPage.html <html><head> <title>Web Page Loading Applet</title></head> <body> <h1>Web Page Loading Applet</h1> <P>Applet is placed here... <applet code="ShowPage.class" width=300 height=50> </applet> </P> </body></html> 240-322 Cli/Serv.: jnet/11 51 showPage.java import import import import java.net.*; javax.swing.*; java.applet.AppletContext; javax.swing.JOptionPane; public class ShowPage extends JApplet { public void init() { try { String urlString = JOptionPane.showInputDialog( "Enter a URL:"); URL url = new URL(urlString); : 240-322 Cli/Serv.: jnet/11 52 AppletContext browser = getAppletContext(); browser.showDocument(url); } catch (Exception e) { System.out.println(e); } } // end of init() } // end of ShowPage 240-322 Cli/Serv.: jnet/11 53 Notes The download only works because the browser is set up to work through cache. There are no Java security restrictions on a applet passing a URL to a browser to be displayed. 240-322 Cli/Serv.: jnet/11 continued 54 A URL is downloaded with showDocument(), which must be called in the applet’s environment (i.e. the browser): – AppletContext browser = getAppletContext(); browser.showDocument(url); The URL is automatically loaded into the browser, replacing showPage.html. 240-322 Cli/Serv.: jnet/11 continued 55 There is a two-argument version of showDocument() that can load URLs into frames. D&D contains a more complex example (SiteSelector.java, ch. 21) which allows the user to select a URL from a list. 240-322 Cli/Serv.: jnet/11 56 4.4. Displaying a URL with JEditorPane The Swing GUI includes JEditorPane which allows 'structured' text to be displayed and edited. – offers basic support for plain text, RTF, and HTML – see javax.swing.JEditorPane 240-322 Cli/Serv.: jnet/11 continued 57 A JEditorPane can be filled by calling setPage() with a URL string argument. also has support for capturing hyperlink clicks as events. JEditorPane 240-322 Cli/Serv.: jnet/11 continued 58 With these features, it is possible to write a basic Web browser! has a text field for the user to enter a URL ShowURLPage.java – the resulting downloaded page is displayed in a JEditorPane – if a link is clicked inside the pane, then its page will be loaded automatically 240-322 Cli/Serv.: jnet/11 continued 59 I clicked on “School of Advanced...” 240-322 Cli/Serv.: jnet/11 60 ShowURLPage’s Event Model X GUI enter contents ^ action events hyperlink events Code 240-322 Cli/Serv.: jnet/11 hyperlinkUpdate() {...} actionPerformed() {...} 61 ShowURLPage.java import import import import import import java.awt.*; java.awt.event.*; java.net.*; java.io.*; javax.swing.*; javax.swing.event.*; public class ShowURLPage extends JFrame { private JTextField enter; private JEditorPane contents; : 240-322 Cli/Serv.: jnet/11 62 public ShowURLPage() { super("Simple Web Browser"); Container c = getContentPane(); enter = new JTextField("Enter file URL here"); enter.addActionListener(new ActionListener() { public void actionPerformed(ActionEvent e ) { getPage(e.getActionCommand());} }); c.add(enter, BorderLayout.NORTH); : 240-322 Cli/Serv.: jnet/11 63 contents = new JEditorPane(); contents.setEditable(false); contents.addHyperlinkListener( new HyperlinkListener() { public void hyperlinkUpdate( HyperlinkEvent e) { if(e.getEventType() == HyperlinkEvent.EventType.ACTIVATED) getPage(e.getURL().toString()); } }); : 240-322 Cli/Serv.: jnet/11 64 c.add( new JScrollPane(contents), BorderLayout.CENTER); setDefaultCloseOperation( JFrame.EXIT_ON_CLOSE); setSize(400, 300); setVisible(true); } // end of ShowURLPage() 240-322 Cli/Serv.: jnet/11 65 private void getPage(String location) { setCursor(Cursor.getPredefinedCursor( Cursor.WAIT_CURSOR)); try { contents.setPage(location); enter.setText(location); } catch (IOException io) { JOptionPane.showMessageDialog(this, "Error retrieving specified URL", "Bad URL", JOptionPane.ERROR_MESSAGE); } setCursor( Cursor.getPredefinedCursor( Cursor.DEFAULT_CURSOR) ); } // end of getPage() 240-322 Cli/Serv.: jnet/11 66 public static void main(String args[]) { new ShowURLPage(); } } // end of ShowURLPage class 240-322 Cli/Serv.: jnet/11 67 Use C> javac ShowURLPage.java C> java ShowURLPage // A request for http://www.cs.ait.ac.th/~ad // causes a “Bad URL” dialog box to appear C> java -DproxySet=true -DproxyHost=cache.psu.ac.th -DproxyPort=8080 ShowURLPage Typed all on one line. The window shown on the left of slide 60 appears. 240-322 Cli/Serv.: jnet/11 68 Notes The JEditorPane must be set uneditable so that hyperlinks events can be captured. events include: ENTERED, EXITED, and ACTIVATED. Hyperlink – see javax.swing.event.HyperlinkEvent 240-322 Cli/Serv.: jnet/11 continued 69 getPage() calls setPage() to display a URL in the JEditorPane – the call is surrounded by changes to the cursor icon so things look busy getPage() is called in two possible ways: – as a response to pressing enter in the textfield – as a response to a link being clicked 240-322 Cli/Serv.: jnet/11 70 5. A Stream Socket Client/Server AlienClient.java AlienServer1.java Initial Internet 4444 Server socket connection socket input and output streams 240-322 Cli/Serv.: jnet/11 socket for client comms. input and output streams the new socket is made with accept() 71 The server creates a new socket when a client contacts it – client/server communication via the new socket – this frees up the main server socket to receive connections from other clients – AlienServer1.java is an iterative server it 240-322 Cli/Serv.: jnet/11 can only process one client at a time continued 72 Our client and server both run on localhost. AlienServer1 actions: – wait for a client connection – after a connection, wait for a message from the client – respond depending on the content of the message – close the client connection, and loop, waiting for another client 240-322 Cli/Serv.: jnet/11 continued 73 Diagram for Client Processing AlienClient.java AlienServer1.java 1. send message 4. send answer 2. analyse message 3. print message locally 5. close socket 240-322 Cli/Serv.: jnet/11 74 AlienServer1.java import java.io.*; import java.net.*; public class AlienServer1 { public static void main(String args[]) throws IOException { Socket sock; BufferedReader in; PrintStream out; ServerSocket servsock = new ServerSocket(4444); : 240-322 Cli/Serv.: jnet/11 75 while (true) { // wait for the next client connection sock = servsock.accept(); // Get I/O streams from the socket out = new PrintStream( sock.getOutputStream() ); in = new BufferedReader( new InputStreamReader( sock.getInputStream() ) ); : 240-322 Cli/Serv.: jnet/11 76 // get client message and respond String msg = in.readLine(); System.out.println(" Received: " + msg); if (msg.indexOf("hello") > -1) { System.out.println(" Friendly contact made"); out.println("Welcome friend"); } else { System.out.println(" Probably an alien"); out.println("ET go home"); } out.flush(); // Close this connection, // (not the overall server socket) sock.close(); } } // of main() }// end of AlienServer1 240-322 Cli/Serv.: jnet/11 77 The client: AlienClient.java AlienClient.java’s – – – – actions: open a connection with the server send a message taken from the command line receive and print the server’s response close 240-322 Cli/Serv.: jnet/11 78 AlienClient.java import java.io.*; import java.net.*; public class AlienClient { public static void main(String args[]) throws IOException { Socket sock = new Socket("localhost", 4444); // Get I/O streams from the socket BufferedReader br = new BufferedReader( new InputStreamReader( sock.getInputStream()) ); PrintStream ps = new PrintStream( sock.getOutputStream() ); : 240-322 Cli/Serv.: jnet/11 79 // Send a message from the command line ps.println(args[0]); ps.flush(); // Read server’s response String line = br.readLine(); System.out.println( "Got this from server:\n " + line); sock.close(); } // end of main() } // end of AlienClient class 240-322 Cli/Serv.: jnet/11 80 Use Client: Server: I used two separate DOS windows on the same machine. 240-322 Cli/Serv.: jnet/11 81 Telnet Client (from fivedots) I typed this Server: 240-322 Cli/Serv.: jnet/11 82 A More Complex Example D&D gives a larger stream socket client/server example (ch. 21): – object input and output streams are used – the sequence of communication is more complex the client maintains a long-lived link with the server until it sends a “TERMINATE” string 240-322 Cli/Serv.: jnet/11 83 5.1. A Concurrent Server uses threads to handle multiple clients concurrently. AlienServer2.java Three main advantages: – the server code is simpler since server processing is in a separate class called Worker – clients do not have to wait – the server is more scaleable 240-322 Cli/Serv.: jnet/11 84 AlienServer2 Visually AlienServer2 AlienClient clients 4444 Worker threads each Worker thread can deal with multiple messages from its client 240-322 Cli/Serv.: jnet/11 85 5.2. Java Threads (Briefly) There are two ways to create a thread: – extend the Thread class – write a class to implement the Runnable interface use the first approach since Worker does not need to extend any other classes. We 240-322 Cli/Serv.: jnet/11 continued 86 A class extended from Thread must define the run() method: class Worker extends Thread { public void run() { ... } } A threaded start(): object is started by calling Worker w = new Worker(...): w.start(); The thread will call run() itself from within start(). 240-322 Cli/Serv.: jnet/11 87 5.3. AlienServer2.java import java.io.*; import java.net.*; public class Worker extends Thread { private Socket sock; private int id; public Worker(Socket s, int c) { sock = s; id = c; } : 240-322 Cli/Serv.: jnet/11 88 public void run() { // Get I/O streams from the socket try { PrintStream out = new PrintStream( sock.getOutputStream() ); BufferedReader in = new BufferedReader( new InputStreamReader( sock.getInputStream() )); : 240-322 Cli/Serv.: jnet/11 89 The worker contains much the same client processing code as the iterative server. // get client messages and respond String msg; while ((msg = in.readLine()) != null) { System.out.println(" Worker "+id+ " received: "+ msg); if (msg.indexOf("hello") > -1) out.println("Welcome friend") else out.println("ET go home"); out.flush(); } : 240-322 Cli/Serv.: jnet/11 90 // Close this connection, // (not the overall server socket) System.out.println(" Worker " + id + " finished"); sock.close(); } catch(IOException ioe) {System.out.println(ioe); } } // end of run() } // end of Worker class 240-322 Cli/Serv.: jnet/11 91 public class AlienServer2 { public static void main(String args[]) throws IOException { Socket sock; ServerSocket servsock = new ServerSocket(4444, 6); while (true) { // wait for the next client connection sock = servsock.accept(); new Worker(sock).start(); } } // of main() } // of AlienServer2 class 240-322 Cli/Serv.: jnet/11 92 Use 240-322 Cli/Serv.: jnet/11 Server: 93 Client on fivedots 240-322 Cli/Serv.: jnet/11 94 Two Local Clients (one closed) 240-322 Cli/Serv.: jnet/11 95 6. A Datagram Socket Client/Server UDPClient Datagram socket UDPServer packets any port msg 5000 Datagram socket echo 240-322 Cli/Serv.: jnet/11 96 6.1. Server Event Model X ^ display 1) receive from client GUI Code waitForPackets() {...} packet packet 240-322 Cli/Serv.: jnet/11 2) echo back to client 97 6.2. UDPServer.java import import import import import java.io.*; java.net.*; java.awt.*; java.awt.event.*; javax.swing.*; public class UDPServer extends JFrame { private JTextArea display; : 240-322 Cli/Serv.: jnet/11 98 public UDPServer() { super("UDP Server"); display = new JTextArea(); getContentPane().add( new JScrollPane( display), BorderLayout.CENTER ); setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); setSize(400, 300); show(); DatagramSocket socket = null; try { socket = new DatagramSocket( 5000 ); } catch(SocketException se) { se.printStackTrace(); System.exit(1); } waitForPackets(socket); } // end of UDPServer() 240-322 Cli/Serv.: jnet/11 99 private void waitForPackets(DatagramSocket socket) { DatagramPacket sendPacket, receivePacket; while (true) { try { // set up packet data structure byte data[] = new byte[100]; receivePacket = new DatagramPacket(data, data.length); // wait for packet from client socket.receive(receivePacket); : 240-322 Cli/Serv.: jnet/11 100 // process client packet display.append("\nPacket received:" + "\nFrom host: "+receivePacket.getAddress()+ "\nHost port: " + receivePacket.getPort() + "\nLength: " + receivePacket.getLength() + "\nContaining:\n\t" + new String(receivePacket.getData(), 0, receivePacket.getLength())); : 240-322 Cli/Serv.: jnet/11 101 // echo packet info back to client display.append( "\n\nEcho data to client..."); sendPacket = new DatagramPacket( receivePacket.getData(), receivePacket.getLength(), receivePacket.getAddress(), receivePacket.getPort() ); socket.send( sendPacket ); display.append("Packet sent\n"); display.setCaretPosition( display.getText().length() ); } : 240-322 Cli/Serv.: jnet/11 102 catch(IOException io) { display.append(io.toString() + "\n"); io.printStackTrace(); } } } // end of waitForPackets{} public static void main( String args[] ) { new UDPServer(); } } // end of UDPServer 240-322 Cli/Serv.: jnet/11 103 Server Notes The server creates one datagram socket at port 5000: socket = new DatagramSocket(5000); Datagram socket creation must be inside a try/catch block. 240-322 Cli/Serv.: jnet/11 continued 104 The server loops inside waitForPackets() – creates an empty packet (100 bytes long) – blocks inside receive() When receive() returns, the packet contains data and: – the Internet address of the sender – the port number of the sender – the actual length of the data 240-322 Cli/Serv.: jnet/11 continued 105 The packet information can be accessed via methods. e.g.: receivePacket.getPort(); receivePacket.getData(); receive() 240-322 Cli/Serv.: jnet/11 must be in a try/catch block. continued 106 The server echoes the datagram back to the client at the address and port obtained from the client’s message: sendPacket = new DatagramPacket( receivePacket.getData(), receivePacket.getLength(), receivePacket.getAddress(), receivePacket.getPort() ); socket.send(sendPacket); send() 240-322 Cli/Serv.: jnet/11 must be in a try/catch block. 107 6.3. Client Event Model X GUI enter ^ display Code 1) send to server actionPerformed() {...} waitForPackets() {...} 2) receive echo from sender 240-322 Cli/Serv.: jnet/11 action events packet packet 108 6.4. UDPClient.java import import import import import java.io.*; java.net.*; java.awt.*; java.awt.event.*; javax.swing.*; public class UDPClient extends JFrame implements ActionListener { private JTextField enter; private JTextArea display; private DatagramSocket socket; : 240-322 Cli/Serv.: jnet/11 109 public UDPClient() { super("UDP Client"); enter = new JTextField("Type message here"); enter.addActionListener(this); getContentPane().add(enter,BorderLayout.NORTH); display = new JTextArea(); getContentPane().add(new JScrollPane(display), BorderLayout.CENTER); setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); setSize(400, 300); setVisible(true); : 240-322 Cli/Serv.: jnet/11 110 try { socket = new DatagramSocket(); } catch(SocketException se) { se.printStackTrace(); System.exit(1); } waitForPackets(); } // end of UDPClient() 240-322 Cli/Serv.: jnet/11 111 private void waitForPackets() { DatagramPacket receivePacket; while (true) { try { // set up packet data structure byte data[] = new byte[100]; receivePacket = new DatagramPacket(data, data.length); // wait for packet from server socket.receive(receivePacket); : 240-322 Cli/Serv.: jnet/11 112 // process packet from server display.append("\nPacket received:" + "\nFrom host: "+receivePacket.getAddress()+ "\nHost port: " + receivePacket.getPort() + "\nLength: " + receivePacket.getLength() + "\nContaining:\n\t" + new String( receivePacket.getData(), 0, receivePacket.getLength())); display.setCaretPosition( display.getText().length() ); } catch(IOException ex) { display.append(ex.toString()+"\n" ); ex.printStackTrace(); } } } // end of waitForPackets() 240-322 Cli/Serv.: jnet/11 113 public void actionPerformed(ActionEvent e) { DatagramPacket sendPacket; try { display.append( "\nSending packet containing: " + e.getActionCommand() + "\n" ); String s = e.getActionCommand(); byte data[] = s.getBytes(); sendPacket = new DatagramPacket( data, data.length, InetAddress.getLocalHost(), 5000); socket.send(sendPacket); : 240-322 Cli/Serv.: jnet/11 114 display.append("Packet sent\n"); display.setCaretPosition( display.getText().length() ); } catch (IOException ex) { display.append(ex.toString()+"\n"); ex.printStackTrace(); } } // end of actionPerformed() public static void main( String args[] ) { new UDPClient(); } } // end of UDPClient 240-322 Cli/Serv.: jnet/11 115 Client Notes The client gets the data for each packet from the user entering a string into a TextField. The client creates a datagram socket with no specified port number: socket = new DatagramSocket(); 240-322 Cli/Serv.: jnet/11 continued 116 In actionPerformed(), the user’s input is converted into a packet, and sent to the server: sendPacket = new DatagramPacket( data, data.length(), InetAddress.getLocalHost(), 5000); socket.send(sendPacket); The code assumes that the server is on the same machine as the client, and attached to port 5000. 240-322 Cli/Serv.: jnet/11 continued 117 The client receives the echoed reply in waitForPackets(): – the loop blocks inside receive() until a packet arrives from the server – the packet details are displayed in the JTextArea The blocked waitForPackets() does not stop the user from entering more strings for the client to send out – the GUI always runs in a separate thread 240-322 Cli/Serv.: jnet/11 118 Tested by starting the client and server in two separate DOS windows. 6.5. Use 1. message sent to server 3. Echoed message received from the server 240-322 Cli/Serv.: jnet/11 2. Client message received and echoed continued 119 Another message sent and echoed back: 240-322 Cli/Serv.: jnet/11 120 7. Networked Tic-Tac-Toe D&D Section 21.8, p.1031 Server thread thread synchronized validMove() 5000 data Client: Player ‘X’ Client: Player ‘O’ thread thread 240-322 Cli/Serv.: jnet/11 data 121 Output 240-322 Cli/Serv.: jnet/11 p.1041-1042 122 8. More Information Chapter 21, Deitel & Deitel (D&D) http://java.coe.psu.ac.th/ForMember/ Books.html#Network Killer Game Programming in Java Chapter 29, Network Basics http://fivedots.coe.psu.ac.th/~ad/jg/ch18/ 240-322 Cli/Serv.: jnet/11 123 Core Java 2, Vol II - Advanced Features Cay S. Horstmann & Gary Cornell Sun Microsystems Press, 2001, chapter 3 – multithreaded server, sending e-mail, URLConnection, HTTP POST – http://java.coe.psu.ac.th/ForMember/ Books.html#Network 240-322 Cli/Serv.: jnet/11 124 Aj. Somchai's Java Site – Network and Distributed Programming Books http://java.coe.psu.ac.th/ForMember/ Books.html#Network 240-322 Cli/Serv.: jnet/11 125