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
Stock Market Quotes – Socket Version • The screen will display a stock market ticker We will reuse our scrolling banner ! • We will develop two different approaches • Client Pull – the client periodically contacts the server and requests updates • Server Push – the client supplies a list of stocks it is watching and the server notifies the client whenever one of these stock changes • We develop the same two approaches use RMI (Remote Method Invocation) in the next section The Overall Design • Here is the class diagram showing the new classes • Here is how the program operates • The client contacts the server for an update • The server sends back a complete list of (name quote) pairs for all stocks • The client picks out those it wants to display Fields and Methods in the Ticker Class A Generic Ticker Banner Class - 1 public class Ticker extends DBAnimationApplet { public void initQuotes() {} public void initAnimator() { String att = getParameter("delay"); if (att != null) { setDelay(Integer.parseInt(att)); } watch = getParameter("watch"); if (att != null) { StringTokenizer tk = new StringTokenizer(watch); Vector v = new Vector(); while (tk.hasMoreTokens()) { v.addElement(tk.nextToken()); } n = v.size(); symbol = new String[n]; quote = new String[n]; for (int i = 0; i < n; i++) { symbol[i] = (String) v.elementAt(i); quote[i] = "0"; } } url = getDocumentBase(); initQuotes(); updateQuotes(); text1 = text2; x = d.width; y = font.getSize(); } A Generic Ticker Banner Class - 2 public void paintFrame(Graphics g) { g.setColor(Color.black); g.fillRect(0,0,d.width,d.height); // set the font and color, and draw the text g.setFont(font); g.setColor(Color.green); g.drawString(text1 + text2, x, y); // get the font metrics to determine the length of the text FontMetrics fm = g.getFontMetrics(); int length = fm.stringWidth(text1); // adjust the position of text for the next frame x -= offset; // if the text is completely off to the left end // move the position back to the right end if (x < -length) { x = 0; text1 = text2; updateQuotes(); } } A Generic Ticker Banner Class - 3 protected synchronized void updateQuotes() { StringBuffer sb = new StringBuffer(); for (int i = 0; i < n; i++) { sb.append(symbol[i] + " " + quote[i] + " } text2 = sb.toString(); } protected String text1, text2; protected Font font = new java.awt.Font("Helvetica", Font.BOLD, 24); protected int speed = 100; protected int offset = 1; protected int x, y; protected int n; protected String symbol[], quote[]; protected URL url; protected String watch; } "); public class TickerPullClient extends Ticker { TickerPullClient protected void updateQuotes() { int i; try { Socket t = new Socket(url.getHost(), 8001); BufferedReader in = new BufferedReader(new InputStreamReader(t.getInputStream())); String line; while ((line = in.readLine()) != null) { StringTokenizer tk = new StringTokenizer(line); String name = tk.nextToken(); for (i = 0; i < n; i++) { if (symbol[i].equals(name)) { String newquote = tk.nextToken(); quote[i] = newquote; } } } t.close(); } catch (IOException e) {} super.updateQuotes(); } } /* Protocol --- Ticker client pull Port: 8001 Client: connect Server: name1 quote1 name2 quote2 ... Server: disconnect The Server Side - 1 Server design: two threads: client handler, quote generator no synchronization necessary for quote[] */ public class QuotePullServer extends Thread { static protected String symbol[] = { "IBM", "Sun", "Intel", "Apple", "Compaq" }; static protected int quote[] = { 100, 100, 100, 100, 100 }; static protected int n = 5; public static void main(String[] args) { System.out.println("QuotePullServer started."); new QuotePullServer().start(); try { ServerSocket s = new ServerSocket(8001); for (;;) { Socket incoming = s.accept(); PrintWriter out = new PrintWriter( new OutputStreamWriter(incoming.getOutputStream())); for (int i = 0; i < n; i++) { out.println(symbol[i] + " " + quote[i]); } out.flush(); out.close(); incoming.close(); } } catch (Exception e) { System.err.println(e); } System.out.println("QuotePullServer stopped."); The Server Side - 2 } The Server Side - 3 public void run() { while (true) { try { Thread.currentThread().sleep(10000); System.out.println("New quote:"); for (int i = 0; i < n; i++) { quote[i] += (Math.random()-0.4)*( 10.0*Math.random()); System.out.println(symbol[i] + " " + quote[i]); } System.out.println("End quote."); } catch (Exception e) { System.err.println(e); } } } } The html File <title>Java Applet Demo: Ticker</title> <h1>Ticker</h1> <hr> <applet code="TickerPullClient.class" width=200 height=30> <param name=delay value="100"> <param name=watch value="Sun Intel IBM"> </applet> <p> <hr> <applet code="TickerPullClient.class" width=200 height=30> <param name=speed value="100"> <param name=watch value="Sun Apple Compaq"> </applet> <hr> <a href="TickerPullClient.java">The pull client.</a> <br> <a href="QuotePullServer.java">The pull server.</a> <br> Server Push Implementation • The sequence of operations Server Push Design • Notice that we reuse our generic Ticker class /* Protocol --- Ticker client pull Port: 8002 Client: connect Client: WATCH name1 name2 ... Server: name1 quote1 // send all quotes the first time name2 quote2 ... Server: DONE Server: name quote // resend quote when changed Server: name quote ... Client: CLOSE Client design: two threads: animator, quote listener animator waits until all quotes are in no synchronization necessary for quote[] */ The Client Side TickerPushClient - 1 public class TickerPushClient extends Ticker { protected Socket socket; protected PrintWriter out; protected QuoteListener quotelistener; public void initQuotes() { try { socket = new Socket(url.getHost(), 8002); out = new PrintWriter(new OutputStreamWriter(socket.getOutputStream())); out.println("WATCH " + watch); out.flush(); System.out.println("Send: " + "WATCH " + watch); BufferedReader in = new BufferedReader(new InputStreamReader(socket.getInputStream())); String line; while ((line = in.readLine()) != null) { System.out.println("Receive: " + line); if (line.trim().equals("DONE")) { break; } TickerPushClient - 2 StringTokenizer tk = new StringTokenizer(line); String name = tk.nextToken(); for (int i = 0; i < n; i++) { if (symbol[i].equals(name)) { String newquote = tk.nextToken(); quote[i] = newquote; } } } out.flush(); quotelistener = new QuoteListener(this, in); quotelistener.start(); } catch (IOException e) { System.err.println(e); } } public void destroy() { out.println("CLOSE"); quotelistener.interrupt(); } } class QuoteListener extends Thread { public QuoteListener(TickerPushClient ticker, BufferedReader in) { this.ticker = ticker; this.in = in; } public void run() { String line; try { while ((line = in.readLine()) != null) { System.out.println("Receive: " + line); StringTokenizer tk = new StringTokenizer(line); String name = tk.nextToken(); for (int i = 0; i < ticker.n; i++) { if (ticker.symbol[i].equals(name)) { String newquote = tk.nextToken(); ticker.quote[i] = newquote; } } if (isInterrupted()) { break; } } in.close(); } catch (IOException e) { System.out.println(e); } } QuoteListener public class QuotePushServer extends Thread { static static static static protected protected protected protected String int int Vector symbol[] = { "IBM", "Sun", "Intel", "Apple", "Compaq" }; quote[] = { 100, 100, 100, 100, 100 }; n = 5; clients = new Vector(); public static void main(String[] args) { System.out.println("QuotePullServer started."); new QuotePushServer().start(); try { ServerSocket s = new ServerSocket(8002); // Waiting for new clients for (;;) { Socket incoming = s.accept(); ClientHandler newClient = new ClientHandler(incoming); clients.addElement(newClient); newClient.start(); } } catch (Exception e) { System.err.println(e); } QuotePushServer - 1 System.out.println("QuotePullServer stopped."); } static public int getQuote(String name) { for (int i = 0; i < n; i++) { if (symbol[i].equals(name)) ( return quote[i]; } } return 0; } // update quote public void run() { while (true) { try { Thread.currentThread().sleep(10000); System.out.println("New quote:"); for (int i = 0; i < n; i++) { int dq = 0; if (Math.random() < 0.5) { dq = (int) ((Math.random() - 0.4) * ( 10.0 * Math.random())); } if (dq > 0) { quote[i] += dq; System.out.println("Changed: " + symbol[i] + " " + quote[i]); Enumeration enum = clients.elements(); while (enum.hasMoreElements()) { ClientHandler t = (ClientHandler) enum.nextElement(); t.updateQuote(symbol[i], quote[i]); } } } System.out.println("End quote."); } catch (Exception e) { System.err.println(e); } } } QuotePushServer - 2 } class ClientHandler extends Thread { protected PrintWriter out; protected BufferedReader in; protected Socket socket; protected String symbol[]; protected int n; ClientHandler - 1 public ClientHandler (Socket socket) { this.socket = socket; try { out = new PrintWriter(new OutputStreamWriter(socket.getOutputStream())); in = new BufferedReader(new InputStreamReader(socket.getInputStream())); } catch (IOException e) { System.err.println(e); } } public void updateQuote(String name, int quote) // see second slide public void run() // see third slide } ClientHandler - 2 public void updateQuote(String name, int quote) { boolean needToSend = false; int i; if (symbol != null) { for (i = 0; i < n; i++) { if (symbol[i].equals(name)) { needToSend = true; break; } } } else { needToSend = true; } if (needToSend) { out.println(name + " " + quote); out.flush(); } } public void run() { try { String line; while ((line = in.readLine()) != null) { System.out.println("Receive: " + line); if (line.startsWith("WATCH")) { StringTokenizer tk = new StringTokenizer(line); tk.nextToken(); Vector v = new Vector(); while (tk.hasMoreTokens()) { v.addElement(tk.nextToken()); } n = v.size(); symbol = new String[n]; int i; for (i = 0; i < n; i++) { symbol[i] = (String) v.elementAt(i); } for (i = 0; i < n; i++) { out.println(symbol[i] + " " QuotePushServer.getQuote(symbol[i])) } out.println("DONE"); out.flush(); } else if (line.trim().equals("CLOSE")) { break; } } socket.close(); in.close(); out.close(); } catch (IOException e) { System.err.println(e); } QuotePushServer.clients.removeElement(this); } Run responds to two messages: WATCH and CLOSE ClientHandler - 3 Using Sockets for a Chat Room • Briefly describe your approach to solve the following problem Use Sockets to Play Tic-Tac-Toe • Describe how sockets could be used to adapt the tic-tac-toe game so it can be played from two different clients remotely