Java/Tiny Application/Chat

Материал из Java эксперт
Перейти к: навигация, поиск

Chat client server

   <source lang="java">

/**

* ChatClient.java  1.00 96/11/07 Merlin Hughes
*
* Copyright (c) 1996 Prominence Dot Com, Inc. All Rights Reserved.
*
* Permission to use, copy, modify, and distribute this software
* for non-commercial purposes and without fee is hereby granted
* provided that this copyright notice appears in all copies.
*
* http://prominence.ru/                  merlin@prominence.ru
*/

import java.net.*; import java.io.*; import java.awt.*; public class ChatClient extends Frame implements Runnable {

 protected DataInputStream i;
 protected DataOutputStream o;
 protected TextArea output;
 protected TextField input;
 protected Thread listener;
 public ChatClient (String title, InputStream i, OutputStream o) {
   super (title);
   this.i = new DataInputStream (new BufferedInputStream (i));
   this.o = new DataOutputStream (new BufferedOutputStream (o));
   setLayout (new BorderLayout ());
   add ("Center", output = new TextArea ());
   output.setEditable (false);
   add ("South", input = new TextField ());
   pack ();
   show ();
   input.requestFocus ();
   listener = new Thread (this);
   listener.start ();
 }
 public void run () {
   try {
     while (true) {
       String line = i.readUTF ();
       output.appendText (line + "\n");
     }
   } catch (IOException ex) {
     ex.printStackTrace ();
   } finally {
     listener = null;
     input.hide ();
     validate ();
     try {
       o.close ();
     } catch (IOException ex) {
       ex.printStackTrace ();
     }
   }
 }
 public boolean handleEvent (Event e) {
   if ((e.target == input) && (e.id == Event.ACTION_EVENT)) {
     try {
       o.writeUTF ((String) e.arg);
       o.flush ();
     } catch (IOException ex) {
       ex.printStackTrace();
       listener.stop ();
     }
     input.setText ("");
     return true;
   } else if ((e.target == this) && (e.id == Event.WINDOW_DESTROY)) {
     if (listener != null)
       listener.stop ();
     hide ();
     return true;
   }
   return super.handleEvent (e);
 }
 public static void main (String args[]) throws IOException {
   if (args.length != 2)
     throw new RuntimeException ("Syntax: ChatClient <host> <port>");
   Socket s = new Socket (args[0], Integer.parseInt (args[1]));
   new ChatClient ("Chat " + args[0] + ":" + args[1],
                   s.getInputStream (), s.getOutputStream ());
 }

}

////////

/**

* ChatApplet.java  1.00 96/11/01 Merlin Hughes
*
* Copyright (c) 1996 Prominence Dot Com, Inc. All Rights Reserved.
*
* Permission to use, copy, modify, and distribute this software
* for non-commercial purposes and without fee is hereby granted
* provided that this copyright notice appears in all copies.
*
* http://prominence.ru/                  merlin@prominence.ru
*/

import java.net.*; import java.io.*; import java.awt.*; import java.applet.*; // Applet parameters: // host = host name // port = host port public class ChatApplet extends Applet implements Runnable {

 protected DataInputStream i;
 protected DataOutputStream o;
 protected TextArea output;
 protected TextField input;
 protected Thread listener;
 public void init () {
   setLayout (new BorderLayout ());
   add ("Center", output = new TextArea ());
   output.setEditable (false);
   add ("South", input = new TextField ());
   input.setEditable (false);
 }
 public void start () {
   listener = new Thread (this);
   listener.start ();
 }
 public void stop () {
   if (listener != null)
     listener.stop ();
   listener = null;
 }
 public void run () {
   try {
     String host = getParameter ("host");
     if (host == null)
 host = getCodeBase ().getHost ();
     String port = getParameter ("port");
     if (port == null)
 port = "9830";
     output.appendText ("Connecting to " + host + ":" + port + "...");
     Socket s = new Socket (host, Integer.parseInt (port));
     i = new DataInputStream (new BufferedInputStream (s.getInputStream ()));
     o = new DataOutputStream (new BufferedOutputStream (s.getOutputStream ()));
     output.appendText (" connected.\n");
     input.setEditable (true);
     input.requestFocus ();
     execute ();
   } catch (IOException ex) {
     ByteArrayOutputStream out = new ByteArrayOutputStream ();
     ex.printStackTrace (new PrintStream (out));
     output.appendText ("\n" + out);
   }
 }
 public void execute () {
   try {
     while (true) {
       String line = i.readUTF ();
       output.appendText (line + "\n");
     }
   } catch (IOException ex) {
     ByteArrayOutputStream out = new ByteArrayOutputStream ();
     ex.printStackTrace (new PrintStream (out));
     output.appendText (out.toString ());
   } finally {
     listener = null;
     input.hide ();
     validate ();
     try {
       o.close ();
     } catch (IOException ex) {
       ex.printStackTrace ();
     }
   }
 }
 public boolean handleEvent (Event e) {
   if ((e.target == input) && (e.id == Event.ACTION_EVENT)) {
     try {
       o.writeUTF ((String) e.arg);
       o.flush ();
     } catch (IOException ex) {
       ex.printStackTrace();
       listener.stop ();
     }
     input.setText ("");
     return true;
   } else if ((e.target == this) && (e.id == Event.WINDOW_DESTROY)) {
     if (listener != null)
       listener.stop ();
     hide ();
     return true;
   }
   return super.handleEvent (e);
 }

}

/////////// /**

* ChatHandler.java  1.00 96/11/07 Merlin Hughes
*
* Copyright (c) 1996 Prominence Dot Com, Inc. All Rights Reserved.
*
* Permission to use, copy, modify, and distribute this software
* for non-commercial purposes and without fee is hereby granted
* provided that this copyright notice appears in all copies.
*
* http://prominence.ru/                  merlin@prominence.ru
*/

import java.net.*; import java.io.*; import java.util.*; public class ChatHandler extends Thread {

 protected Socket s;
 protected DataInputStream i;
 protected DataOutputStream o;
 public ChatHandler (Socket s) throws IOException {
   this.s = s;
   i = new DataInputStream (new BufferedInputStream (s.getInputStream ()));
   o = new DataOutputStream (new BufferedOutputStream (s.getOutputStream ()));
 }
 protected static Vector handlers = new Vector ();
 public void run () {
   String name = s.getInetAddress ().toString ();
   try {
     broadcast (name + " has joined.");
     handlers.addElement (this);
     while (true) {
       String msg = i.readUTF ();
       broadcast (name + " - " + msg);
     }
   } catch (IOException ex) {
     ex.printStackTrace ();
   } finally {
     handlers.removeElement (this);
     broadcast (name + " has left.");
     try {
       s.close ();
     } catch (IOException ex) {
       ex.printStackTrace();
     }
   }
 }
 protected static void broadcast (String message) {
   synchronized (handlers) {
     Enumeration e = handlers.elements ();
     while (e.hasMoreElements ()) {
       ChatHandler c = (ChatHandler) e.nextElement ();
       try {
         synchronized (c.o) {
           c.o.writeUTF (message);
         }
         c.o.flush ();
       } catch (IOException ex) {
         c.stop ();
       }
     }
   }
 }

} /////////// /**

* ChatServer.java  1.00 96/11/07 Merlin Hughes
*
* Copyright (c) 1996 Prominence Dot Com, Inc. All Rights Reserved.
*
* Permission to use, copy, modify, and distribute this software
* for non-commercial purposes and without fee is hereby granted
* provided that this copyright notice appears in all copies.
*
* http://prominence.ru/                  merlin@prominence.ru
*/

import java.net.*; import java.io.*; import java.util.*; public class ChatServer {

 public ChatServer (int port) throws IOException {
   ServerSocket server = new ServerSocket (port);
   while (true) {
     Socket client = server.accept ();
     System.out.println ("Accepted from " + client.getInetAddress ());
     ChatHandler c = new ChatHandler (client);
     c.start ();
   }
 }
 public static void main (String args[]) throws IOException {
   if (args.length != 1)
     throw new RuntimeException ("Syntax: ChatServer <port>");
   new ChatServer (Integer.parseInt (args[0]));
 }

}

 </source>
   
  
 
  



Simple console-mode (command-line) chat client

   <source lang="java">

/*

* Copyright (c) Ian F. Darwin, http://www.darwinsys.ru/, 1996-2002.
* All rights reserved. Software written by Ian F. Darwin and others.
* $Id: LICENSE,v 1.8 2004/02/09 03:33:38 ian Exp $
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
*    notice, this list of conditions and the following disclaimer.
* 2. Redistributions 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.
*
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS""
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
* TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
* PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS
* BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGE.
* 
* Java, the Duke mascot, and all variants of Sun"s Java "steaming coffee
* cup" logo are trademarks of Sun Microsystems. Sun"s, and James Gosling"s,
* pioneering role in inventing and promulgating (and standardizing) the Java 
* language and environment is gratefully acknowledged.
* 
* The pioneering role of Dennis Ritchie and Bjarne Stroustrup, of AT&T, for
* inventing predecessor languages C and C++ is also gratefully acknowledged.
*/

import java.applet.*; import java.awt.*; import java.awt.event.*; import java.net.*; import java.io.*; import java.net.*; import java.util.*; /** Simple console-mode (command-line) chat client.

* @author Ian Darwin, http://www.darwinsys.ru/
* @version $Id: ConsChat.java,v 1.6 2004/02/16 02:44:43 ian Exp $
*/

public class ConsChat {

 public static void main(String[] args) throws IOException {
   new ConsChat().chat();
 }
 protected Socket sock;
 protected BufferedReader is;
 protected PrintWriter pw;
 protected BufferedReader cons;
 protected ConsChat() throws IOException {
   sock = new Socket("localhost", Chat.PORTNUM);
   is   = new BufferedReader(new InputStreamReader(sock.getInputStream()));
   pw   = new PrintWriter(sock.getOutputStream(), true);
   cons = new BufferedReader(new InputStreamReader(System.in));
   // Construct and start the reader: from server to stdout.
   // Make a Thread to avoid lockups.
   new Thread() {
     public void run() {
       setName("socket reader thread");
       System.out.println("Starting " + getName());
       System.out.flush();
       String line;
       try {
         // reader thread blocks here
         while ((line = is.readLine()) != null) {
           System.out.println(line);
           System.out.flush();
         }
       } catch (IOException ex) {
         System.err.println("Read error on socket: " + ex);
         return;
       }
     }
   }.start();
 }
 protected void chat() throws IOException {
   String text;
   System.out.print("Login name: "); System.out.flush();
   text = cons.readLine();
   send(Chat.CMD_LOGIN + text);
   // Main thread blocks here
   while ((text = cons.readLine()) != null) {
     if (text.length() == 0 || text.charAt(0) == "#")
       continue;      // ignore null lines and comments
     if (text.charAt(0) == "/")
       send(text.substring(1));
     else send("B"+text);
   }
 }
 protected void send(String s) {
   pw.println(s);
   pw.flush();
 }

} /** Constants and Class Methods for Java Chat Clients and Server.

*
* The protocol:
*  --> Lusername
*  --> Btext_to_broadcast
*  --> Musername\Message
*  --> Q
*  <-- any text to be displayed.
*
* @author Ian Darwin
* @version $Id: Chat.java,v 1.3 2004/02/16 02:44:43 ian Exp $
*/

class Chat {

 // These are the first character of messages from client to server
 public static final int PORTNUM = 9999;
 public static final int MAX_LOGIN_LENGTH = 20;
 public static final char SEPARATOR = "\\";
 public static final char COMMAND = "\\";
 public static final char CMD_LOGIN = "L";
 public static final char CMD_QUIT  = "Q";
 public static final char CMD_MESG  = "M";
 public static final char CMD_BCAST = "B";
 // These are the first character of messages from server to client
 public static final char RESP_PUBLIC = "P";
 public static final char RESP_PRIVATE = "M";
 public static final char RESP_SYSTEM = "S";
 // TODO in main loop:
 // if (text.charAt(0) == "/")
 //    send(text);
 // else send("B"+text);
 public static boolean isValidLoginName(String login) {
   // check length
   if (login.length() > MAX_LOGIN_LENGTH)
     return false;
   // check for bad chars
   // if (contains bad chars)
   //  return false
   // Passed above tests, is OK
   return true;
 }

} /** Trivial Chat Server to go with our Trivial Chat Client.

*
* WARNING -- this code is believed thread-safe but has NOT been 100% vetted 
* by a team of world-class experts for Thread-safeness.
* DO NOT BUILD ANYTHING CRITICAL BASED ON THIS until you have done so.
* See the various books on Threaded Java for design issues.
*
* @author  Ian F. Darwin, http://www.darwinsys.ru/
* @version $Id: ChatServer.java,v 1.10 2004/03/13 21:56:32 ian Exp $
*/

class ChatServer {

 /** What I call myself in system messages */
 protected final static String CHATMASTER_ID = "ChatMaster";
 /** What goes between any handle and the message */
 protected final static String SEP = ": ";
 /** The Server Socket */
 protected ServerSocket servSock;
 /** The list of my current clients */
 protected ArrayList clients;
 /** Debugging state */
 private static boolean DEBUG = false;
 /** Main just constructs a ChatServer, which should never return */
 public static void main(String[] argv) {
   System.out.println("DarwinSys Chat Server 0.1 starting...");
   if (argv.length == 1 && argv[0].equals("-debug"))
     DEBUG = true;
   ChatServer w = new ChatServer();
   w.runServer();      // should never return.
   System.out.println("**ERROR* Chat Server 0.1 quitting");
 }
 /** Construct (and run!) a Chat Service */
 ChatServer() {
   clients = new ArrayList();
   try {
     servSock = new ServerSocket(Chat.PORTNUM);
     System.out.println("DarwinSys Chat Server Listening on port " +
       Chat.PORTNUM);
   } catch(IOException e) {
     log("IO Exception in ChatServer.<init>" + e);
     System.exit(0);
   }
 }
 public void runServer() {
   try {
     while (true) {
       Socket us = servSock.accept();
       String hostName = us.getInetAddress().getHostName();
       System.out.println("Accepted from " + hostName);
       ChatHandler cl = new ChatHandler(us, hostName);
       synchronized (clients) {
         clients.add(cl);
         cl.start();
         if (clients.size() == 1)
           cl.send(CHATMASTER_ID, "Welcome! you"re the first one here");
         else {
           cl.send(CHATMASTER_ID, "Welcome! you"re the latest of " +
             clients.size() + " users.");
         }
       }
     }
   } catch(IOException e) {
     log("IO Exception in runServer: " + e);
     System.exit(0);
   }
 }
 protected void log(String s) {
   System.out.println(s);
 }
 /** Inner class to handle one conversation */
 protected class ChatHandler extends Thread {
   /** The client socket */
   protected Socket clientSock;
   /** BufferedReader for reading from socket */
   protected BufferedReader is;
   /** PrintWriter for sending lines on socket */
   protected PrintWriter pw;
   /** The client"s host */
   protected String clientIP;
   /** String form of user"s handle (name) */
   protected String login;
   /* Construct a Chat Handler */
   public ChatHandler(Socket sock, String clnt) throws IOException {
     clientSock = sock;
     clientIP = clnt;
     is = new BufferedReader(
       new InputStreamReader(sock.getInputStream()));
     pw = new PrintWriter(sock.getOutputStream(), true);
   }
   /** Each ChatHandler is a Thread, so here"s the run() method,
    * which handles this conversation.
    */
   public void run() {
     String line;
     try {
       while ((line = is.readLine()) != null) {
         char c = line.charAt(0);
         line = line.substring(1);
         switch (c) {
         case Chat.CMD_LOGIN:
           if (!Chat.isValidLoginName(line)) {
             send(CHATMASTER_ID, "LOGIN " + line + " invalid");
             log("LOGIN INVALID from " + clientIP);
             continue;
           }
           login = line;
           broadcast(CHATMASTER_ID, login + 
             " joins us, for a total of " + 
             clients.size() + " users");
           break;
         case Chat.CMD_MESG:
           if (login == null) {
             send(CHATMASTER_ID, "please login first");
             continue;
           }
           int where = line.indexOf(Chat.SEPARATOR);
           String recip = line.substring(0, where);
           String mesg = line.substring(where+1);
           log("MESG: " + login + "-->" + recip + ": "+ mesg);
           ChatHandler cl = lookup(recip);
           if (cl == null)
             psend(CHATMASTER_ID, recip + " not logged in.");
           else
             cl.psend(login, mesg);
           break;
         case Chat.CMD_QUIT:
           broadcast(CHATMASTER_ID,
             "Goodbye to " + login + "@" + clientIP);
           close();
           return;    // The end of this ChatHandler
           
         case Chat.CMD_BCAST:
           if (login != null)
             broadcast(login, line);
           else
             log("B<L FROM " + clientIP);
           break;
         default:
           log("Unknown cmd " + c + " from " + login + "@" + clientIP);
         }
       }
     } catch (IOException e) {
       log("IO Exception: " + e);
     } finally {
       // the sock ended, so we"re done, bye now
       System.out.println(login + SEP + "All Done");
       synchronized(clients) {
         clients.remove(this);
         if (clients.size() == 0) {
           System.out.println(CHATMASTER_ID + SEP +
             "I"m so lonely I could cry...");
         } else if (clients.size() == 1) {
           ChatHandler last = (ChatHandler)clients.get(0);
           last.send(CHATMASTER_ID,
             "Hey, you"re talking to yourself again");
         } else {
           broadcast(CHATMASTER_ID,
             "There are now " + clients.size() + " users");
         }
       }
     }
   }
   protected void close() {
     if (clientSock == null) {
       log("close when not open");
       return;
     }
     try {
       clientSock.close();
       clientSock = null;
     } catch (IOException e) {
       log("Failure during close to " + clientIP);
     }
   }
   /** Send one message to this user */
   public void send(String sender, String mesg) {
     pw.println(sender + SEP + mesg);
   }
   /** Send a private message */
   protected void psend(String sender, String msg) {
     send("<*" + sender + "*>", msg);
   }
   
   /** Send one message to all users */
   public void broadcast(String sender, String mesg) {
     System.out.println("Broadcasting " + sender + SEP + mesg);
     for (int i=0; i<clients.size(); i++) {
       ChatHandler sib = (ChatHandler)clients.get(i);
       if (DEBUG)
         System.out.println("Sending to " + sib);
       sib.send(sender, mesg);
     }
     if (DEBUG) System.out.println("Done broadcast");
   }
   protected ChatHandler lookup(String nick) {
     synchronized(clients) {
       for (int i=0; i<clients.size(); i++) {
         ChatHandler cl = (ChatHandler)clients.get(i);
         if (cl.login.equals(nick))
           return cl;
       }
     }
     return null;
   }
   /** Present this ChatHandler as a String */
   public String toString() {
     return "ChatHandler[" + login + "]";
   }
 }

} /**

*

* Simple Chat Room Applet. * Writing a Chat Room seems to be one of many obligatory rites (or wrongs) * of passage for Java experts these days.

*

* This one is a toy because it doesn"t have much of a protocol, which * means we can"t query the server as to * who"s logged in, * or anything fancy like that. However, it works OK for small groups.

*

* Uses client socket w/ two Threads (main and one constructed), * one for reading and one for writing.

*

* Server multiplexes messages back to all clients.

* @author Ian Darwin
* @version $Id: ChatRoom.java,v 1.8 2004/03/09 03:59:37 ian Exp $
*/

class ChatRoom extends Applet {

 /** Whether we are being run as an Applet or an Application */
 protected boolean inAnApplet = true;
 /** The state of logged-in-ness */
 protected boolean loggedIn;
 /* The Frame, for a pop-up, durable Chat Room. */
 protected Frame cp;
 /** The default port number */
 protected static int PORTNUM = Chat.PORTNUM;
 /** The actual port number */
 protected int port;
 /** The network socket */
 protected Socket sock;
 /** BufferedReader for reading from socket */
 protected BufferedReader is;
 /** PrintWriter for sending lines on socket */
 protected PrintWriter pw;
 /** TextField for input */
 protected TextField tf;
 /** TextArea to display conversations */
 protected TextArea ta;
 /** The Login button */
 protected Button lib;
 /** The LogOUT button */
 protected Button lob;
 /** The TitleBar title */
 final static String TITLE = "Chat: Ian Darwin"s Toy Chat Room Client";
 /** The message that we paint */
 protected String paintMessage;
 /** init, overriding the version inherited from Applet */
 public void init() {
   paintMessage = "Creating Window for Chat";
   repaint();
   cp = new Frame(TITLE);
   cp.setLayout(new BorderLayout());
   String portNum = null;
   if (inAnApplet)
     portNum = getParameter("port");
   port = PORTNUM;
   if (portNum != null)
     port = Integer.parseInt(portNum);
   // The GUI
   ta = new TextArea(14, 80);
   ta.setEditable(false);    // readonly
   ta.setFont(new Font("Monospaced", Font.PLAIN, 11));
   cp.add(BorderLayout.NORTH, ta);
   Panel p = new Panel();
   Button b;
   // The login button
   p.add(lib = new Button("Login"));
   lib.setEnabled(true);
   lib.requestFocus();
   lib.addActionListener(new ActionListener() {
     public void actionPerformed(ActionEvent e) {
       login();
       lib.setEnabled(false);
       lob.setEnabled(true);
       tf.requestFocus();  // set keyboard focus in right place!
     }
   });
   // The logout button
   p.add(lob = new Button("Logout"));
   lob.setEnabled(false);
   lob.addActionListener(new ActionListener() {
     public void actionPerformed(ActionEvent e) {
       logout();
       lib.setEnabled(true);
       lob.setEnabled(false);
       lib.requestFocus();
     }
   });
   p.add(new Label("Message here:"));
   tf = new TextField(40);
   tf.addActionListener(new ActionListener() {
     public void actionPerformed(ActionEvent e) {
       if (loggedIn) {
         pw.println(Chat.CMD_BCAST+tf.getText());
         tf.setText(""); 
       }
     }
   });
   p.add(tf);
   cp.add(BorderLayout.SOUTH, p);
       cp.addWindowListener(new WindowAdapter() {
     public void windowClosing(WindowEvent e) {
       // If we do setVisible and dispose, then the Close completes
       ChatRoom.this.cp.setVisible(false);
       ChatRoom.this.cp.dispose();
       logout();
     }
   });
   cp.pack();
   // After packing the Frame, centre it on the screen.
   Dimension us = cp.getSize(), 
     them = Toolkit.getDefaultToolkit().getScreenSize();
   int newX = (them.width - us.width) / 2;
   int newY = (them.height- us.height)/ 2;
   cp.setLocation(newX, newY);
   cp.setVisible(true);
   paintMessage = "Window should now be visible";
   repaint();
 }
 protected String serverHost = "localhost";
 /** LOG ME IN TO THE CHAT */
 public void login() {
   showStatus("In login!");
   if (loggedIn)
     return;
   if (inAnApplet)
     serverHost = getCodeBase().getHost();
   try {
     sock = new Socket(serverHost, port);
     is = new BufferedReader(new InputStreamReader(sock.getInputStream()));
     pw = new PrintWriter(sock.getOutputStream(), true);
   } catch(IOException e) {
     showStatus("Can"t get socket to " + 
       serverHost + "/" + port + ": " + e);
     cp.add(new Label("Can"t get socket: " + e));
     return;
   }
   showStatus("Got socket");
   // Construct and start the reader: from server to textarea.
   // Make a Thread to avoid lockups.
   new Thread(new Runnable() {
     public void run() {
       String line;
       try {
         while (loggedIn && ((line = is.readLine()) != null))
           ta.append(line + "\n");
       } catch(IOException e) {
         showStatus("GAA! LOST THE LINK!!");
         return;
       }
     }
   }).start();
   // FAKE LOGIN FOR NOW
   pw.println(Chat.CMD_LOGIN + "AppletUser");
   loggedIn = true;
 }
 /** Log me out, Scotty, there"s no intelligent life here! */
 public void logout() {
   if (!loggedIn)
     return;
   loggedIn = false;
   try {
     if (sock != null)
       sock.close();
   } catch (IOException ign) {
     // so what?
   }
 }
 // It is deliberate that there is no STOP method - we want to keep
 // going even if the user moves the browser to another page.
 // Anti-social? Maybe, but you can use the CLOSE button to kill 
 // the Frame, or you can exit the Browser.
 /** Paint paints the small window that appears in the HTML,
  * telling the user to look elsewhere!
  */
 public void paint(Graphics g) {
   Dimension d = getSize();
   int h = d.height;
   int w = d.width;
   g.fillRect(0, 0, w, 0);
   g.setColor(Color.black);
   g.drawString(paintMessage, 10, (h/2)-5);
 }
 /** a showStatus that works for Applets or non-Applets alike */
 public void showStatus(String mesg) {
   if (inAnApplet)
     super.showStatus(mesg);
   System.out.println(mesg);
 }
 /** A main method to allow the client to be run as an Application */
 public static void main(String[] args) {
   ChatRoom room101 = new ChatRoom();
   room101.inAnApplet = false;
   room101.init();
   room101.start();
 }

}


 </source>