Java tutorial
/* From http://java.sun.com/docs/books/tutorial/index.html */ /* * Copyright (c) 2006 Sun Microsystems, Inc. All Rights Reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are met: * * -Redistribution of source code must retain the above copyright notice, this * list of conditions and the following disclaimer. * * -Redistribution in binary form must reproduce the above copyright notice, * this list of conditions and the following disclaimer in the documentation * and/or other materials provided with the distribution. * * Neither the name of Sun Microsystems, Inc. or the names of contributors may * be used to endorse or promote products derived from this software without * specific prior written permission. * * This software is provided "AS IS," without a warranty of any kind. ALL * EXPRESS OR IMPLIED CONDITIONS, REPRESENTATIONS AND WARRANTIES, INCLUDING * ANY IMPLIED WARRANTY OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE * OR NON-INFRINGEMENT, ARE HEREBY EXCLUDED. SUN MIDROSYSTEMS, INC. ("SUN") * AND ITS LICENSORS SHALL NOT BE LIABLE FOR ANY DAMAGES SUFFERED BY LICENSEE * AS A RESULT OF USING, MODIFYING OR DISTRIBUTING THIS SOFTWARE OR ITS * DERIVATIVES. IN NO EVENT WILL SUN OR ITS LICENSORS BE LIABLE FOR ANY LOST * REVENUE, PROFIT OR DATA, OR FOR DIRECT, INDIRECT, SPECIAL, CONSEQUENTIAL, * INCIDENTAL OR PUNITIVE DAMAGES, HOWEVER CAUSED AND REGARDLESS OF THE THEORY * OF LIABILITY, ARISING OUT OF THE USE OF OR INABILITY TO USE THIS SOFTWARE, * EVEN IF SUN HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES. * * You acknowledge that this software is not designed, licensed or intended * for use in the design, construction, operation or maintenance of any * nuclear facility. */ /* * 1.1 version. */ import java.io.*; import java.net.*; import java.util.*; class TalkServerThread extends Thread { public Socket socket; public BufferedReader is; public BufferedWriter os; TalkServer server; boolean DEBUG = false; public String toString() { return "TalkServerThread: socket = " + socket + "; is = " + is + "; os = " + os; } TalkServerThread(Socket socket, TalkServer server) throws IOException { super("TalkServer"); is = new BufferedReader( new InputStreamReader(socket.getInputStream())); os = new BufferedWriter( new OutputStreamWriter(socket.getOutputStream())); if (is == null) { System.err.println("TalkServerThread: Input stream seemed " + "to be created successfully, but it's null."); throw new IOException(); } if (os == null) { System.err.println("TalkServerThread: Output stream seemed " + "to be created successfully, but it's null."); throw new IOException(); } this.socket = socket; this.server = server; } public void run() { while (socket != null) { try { //Read data. String str = is.readLine(); //Pass it on. if (str != null) { server.forwardString(str, this); } } catch (EOFException e) { //No more data on this socket... server.forwardString("SERVER SAYS other applet disconnected", this); cleanup(); return; } catch (NullPointerException e) { //Socket doesn't exist... server.forwardString("SERVER SAYS no socket to other applet", this); cleanup(); return; } catch (IOException e) { //Read problem.. server.forwardString("SERVER SAYS socket trouble with other applet", this); cleanup(); return; } catch (Exception e) { //Unknown exception. Complain and quit. System.err.println("Exception on is.readLine():"); e.printStackTrace(); cleanup(); return; } } } protected void finalize() { cleanup(); } void cleanup() { try { if (is != null) { is.close(); is = null; } } catch (Exception e) {} //Ignore errors. try { if (os != null) { os.close(); os = null; } } catch (Exception e) {} //Ignore errors. try { if (socket != null) { socket.close(); socket = null; } } catch (Exception e) {} //Ignore errors. } } /* * 1.1 version. */ import java.net.*; import java.io.*; class TalkServer { TalkServerThread[] tstList = new TalkServerThread[2]; boolean DEBUG = false; public static void main(String[] args) { new TalkServer().start(); } public void start() { ServerSocket serverRSocket = null; int numConnected = 0; try { serverRSocket = new ServerSocket(0); System.out.println("TalkServer listening on rendezvous port: " + serverRSocket.getLocalPort()); } catch (IOException e) { System.err.println("Server could not create server socket for rendezvous."); return; } while (true) { //Connect to two clients. while (numConnected < 2) { TalkServerThread tst; tst = connectToClient(serverRSocket); if (tst != null) { numConnected++; if (tstList[0] == null) { tstList[0] = tst; } else { tstList[1] = tst; } } } //end while (numConnected < 2) loop if (DEBUG) { try { System.out.println("tst #0 = " + tstList[0]); } catch (Exception e) {} try { System.out.println("tst #1 = " + tstList[1]); } catch (Exception e) {} } //If they're really OK, tell them to start writing. if (everythingIsOK(0) & everythingIsOK(1)) { for (int i = 0; i < 2; i++) { writeToStream("START WRITING!\n----------------------" + "-------------", tstList[i].os); } } else { System.err.println("2 server threads created, but " + "not everything is OK"); } while (numConnected == 2) { if (!everythingIsOK(0)) { if (DEBUG) { System.out.println("Applet #0 is hosed; disconnecting."); } numConnected--; cleanup(tstList[0]); tstList[0] = null; } if (!everythingIsOK(1)) { if (DEBUG) { System.out.println("Applet #1 is hosed; disconnecting."); } numConnected--; cleanup(tstList[1]); tstList[1] = null; } try { Thread.sleep(1000); } catch (InterruptedException e) { } } //end while(numConnected==2) loop if (DEBUG) { try { System.out.println("Number of connections = " + numConnected); System.out.println("tst #0 = " + tstList[0]); System.out.println("tst #1 = " + tstList[1]); } catch (Exception e) {} } } //end while (true) loop } protected TalkServerThread connectToClient(ServerSocket serverRSocket) { Socket rendezvousSocket = null; TalkServerThread tst = null; //Listen for client connection on the rendezvous socket. try { rendezvousSocket = serverRSocket.accept(); } catch (IOException e) { System.err.println("Accept failed."); e.printStackTrace(); return null; } //Create a thread to handle this connection. try { tst = new TalkServerThread(rendezvousSocket, this); tst.start(); } catch (Exception e) { System.err.println("Couldn't create TalkServerThread:"); e.printStackTrace(); return null; } writeToStream("Successful connection. " + "Please wait for second applet to connect...", tst.os); return tst; } boolean everythingIsOK(int tstNum) { TalkServerThread tst = tstList[tstNum]; if (tst == null) { if (DEBUG) { System.out.println("TalkServerThread #" + tstNum + " is null"); } return false; } else { if (tst.os == null) { if (DEBUG) { System.out.println("TalkServerThread #" + tstNum + " output stream is null."); } return false; } if (tst.is == null) { if (DEBUG) { System.out.println("TalkServerThread #" + tstNum + " input stream is null."); } return false; } if (tst.socket == null) { if (DEBUG) { System.out.println("TalkServerThread #" + tstNum + " socket is null."); } return false; } } return true; } void cleanup(TalkServerThread tst) { if (tst != null) { try { if (tst.os != null) { tst.os.close(); tst.os = null; } } catch (Exception e) {} //Ignore errors try { if (tst.is != null) { tst.is.close(); tst.is = null; } } catch (Exception e) {} //Ignore errors try { if (tst.socket != null) { tst.socket.close(); tst.socket = null; } } catch (Exception e) {} //Ignore errors } } public void forwardString(String string, TalkServerThread requestor) { BufferedWriter clientStream = null; if (tstList[0] == requestor) { if (tstList[1] != null) { clientStream = tstList[1].os; } else { if (DEBUG) { System.out.println("Applet #0 has a string to forward, " + "but Applet #1 is gone..."); } return; } } else { if (tstList[0] != null) { clientStream = tstList[0].os; } else { if (DEBUG) { System.out.println("Applet #1 has a string to forward, " + "but Applet #0 is gone..."); } return; } } if (clientStream != null) { writeToStream(string, clientStream); } else if (DEBUG) { System.out.println("Can't forward string -- no output stream."); } } public void writeToStream(String string, BufferedWriter stream) { if (DEBUG) { System.out.println("TalkServer about to forward data: " + string); } try { stream.write(string); stream.newLine(); stream.flush(); if (DEBUG) { System.out.println("TalkServer forwarded string."); } } catch (IOException e) { System.err.println("TalkServer failed to forward string:"); e.printStackTrace(); return; } catch (NullPointerException e) { System.err.println("TalkServer can't forward string " + "since output stream is null."); return; } } } /* * 1.1 version. */ import java.applet.Applet; import java.awt.*; import java.awt.event.*; import java.io.*; import java.net.*; import java.util.*; public class TalkClientApplet extends Applet implements Runnable, ActionListener { Socket socket; BufferedWriter os; BufferedReader is; TextField portField, message; TextArea display; Button button; int dataPort; boolean trysted; Thread receiveThread; String host; boolean DEBUG = false; String newline; public void init() { //Get the address of the host we came from. host = getCodeBase().getHost(); //Set up the UI. GridBagLayout gridBag = new GridBagLayout(); GridBagConstraints c = new GridBagConstraints(); setLayout(gridBag); message = new TextField(""); c.fill = GridBagConstraints.HORIZONTAL; c.gridwidth = GridBagConstraints.REMAINDER; gridBag.setConstraints(message, c); message.addActionListener(this); add(message); display = new TextArea(10, 40); display.setEditable(false); c.weightx = 1.0; c.weighty = 1.0; c.fill = GridBagConstraints.BOTH; gridBag.setConstraints(display, c); add(display); Label l = new Label("Enter the port (on host " + host + ") to send the request to:", Label.RIGHT); c.fill = GridBagConstraints.HORIZONTAL; c.gridwidth = 1; c.weightx = 0.0; c.weighty = 0.0; gridBag.setConstraints(l, c); add(l); portField = new TextField(6); c.fill = GridBagConstraints.NONE; gridBag.setConstraints(portField, c); portField.addActionListener(this); add(portField); button = new Button("Connect"); gridBag.setConstraints(button, c); button.addActionListener(this); add(button); newline = System.getProperty("line.separator"); } public synchronized void start() { if (DEBUG) { System.out.println("In start() method."); } if (receiveThread == null) { trysted = false; portField.setEditable(true); button.setEnabled(true); os = null; is = null; socket = null; receiveThread = new Thread(this); receiveThread.start(); if (DEBUG) { System.out.println(" Just set everything to null and started thread."); } } else if (DEBUG) { System.out.println(" receiveThread not null! Did nothing!"); } } public synchronized void stop() { if (DEBUG) { System.out.println("In stop() method."); } receiveThread = null; trysted = false; portField.setEditable(true); button.setEnabled(true); notify(); try { //Close input stream. if (is != null) { is.close(); is = null; } } catch (Exception e) { } //Ignore exceptions. try { //Close output stream. if (os != null) { os.close(); os = null; } } catch (Exception e) { } //Ignore exceptions. try { //Close socket. if (socket != null) { socket.close(); socket = null; } } catch (Exception e) { } //Ignore exceptions. } public Insets getInsets() { return new Insets(4, 4, 5, 5); } public void paint(Graphics g) { Dimension d = getSize(); Color bg = getBackground(); g.setColor(bg); g.draw3DRect(0, 0, d.width - 1, d.height - 1, true); g.draw3DRect(3, 3, d.width - 7, d.height - 7, false); } public synchronized void actionPerformed(ActionEvent event) { int port; if (DEBUG) { System.out.println("In action() method."); } if (receiveThread == null) { start(); } if (!trysted) { //We need to attempt a rendezvous. if (DEBUG) { System.out.println(" trysted = false. " + "About to attempt a rendezvous."); } //Get the port the user entered... try { port = Integer.parseInt(portField.getText()); } catch (NumberFormatException e) { //No integer entered. display.append("Please enter an integer below." + newline); return; } //...and rendezvous with it. rendezvous(port); } else { //We've already rendezvoused. Just send data over. if (DEBUG) { System.out.println(" trysted = true. " + "About to send data."); } String str = message.getText(); message.selectAll(); try { os.write(str); os.newLine(); os.flush(); } catch (IOException e) { display.append("ERROR: Applet couldn't write to socket." + newline); display.append("...Disconnecting." + newline); stop(); return; } catch (NullPointerException e) { display.append("ERROR: No output stream!" + newline); display.append("...Disconnecting." + newline); stop(); return; } display.append("Sent: " + str + newline); } } synchronized void waitForTryst() { //Wait for notify() call from action(). try { wait(); } catch (InterruptedException e) { } if (DEBUG) { System.out.println("waitForTryst about to return. " + "trysted = " + trysted + "."); } return; } public void run() { String received = null; waitForTryst(); //OK, now we can send messages. while (Thread.currentThread() == receiveThread) { try { //Wait for data from the server. received = is.readLine(); //Display it. if (received != null) { display.append("Received: " + received + newline); } else { //success but no data... System.err.println("End of stream?"); return; //XXX } } catch (IOException e) { //Perhaps a temporary problem? display.append("NOTE: Couldn't read from socket.\n"); return; } } } private void rendezvous(int port) { //Try to open a socket to the port. try { socket = new Socket(host, port); } catch (UnknownHostException e) { display.append("ERROR: Can't find host: " + host + newline); return; } catch (IOException e) { display.append( "ERROR: Can't open socket on rendezvous port " + port + " (on host " + host + ")." + newline); return; } //Try to open streams to read and write from the socket. try { os = new BufferedWriter(new OutputStreamWriter(socket.getOutputStream())); is = new BufferedReader(new InputStreamReader(socket.getInputStream())); } catch (IOException e) { display.append("ERROR: Created data socket but can't " + "open stream on it." + newline); display.append("...Disconnecting." + newline); stop(); return; } if ((os != null) & (is != null)) { if (DEBUG) { System.out.println("Successful rendezvous."); System.out.println("socket = " + socket); System.out.println("output stream = " + os); System.out.println("input stream = " + is); } //Let the main applet thread know we've successfully rendezvoused. portField.setEditable(false); button.setEnabled(false); trysted = true; notify(); } else { display.append("ERROR: Port is valid but communication failed. " + "Please TRY AGAIN." + newline); } } }