package talk; import java.util.Vector; import java.util.Enumeration; import java.net.*; import java.io.*; // This is an app, not an applet. Any public class // with a 'public static void main(String argv[])' method // can be launched as an app by typing 'java Classname' public class Server implements Runnable { // The socket we will listen for new callers with. ServerSocket listener; // The vector we will keep a list of connections in. Vector connections; // The thread that listens for connections. Thread listenerThread; // This is the entry point for a java app. public static void main(String argv[]) { // Find out what port to listen on. if (argv.length != 1) { usage(); } int port = 0; try { port = Integer.parseInt(argv[0]); } catch (java.lang.NumberFormatException e) { System.out.println("Bad port parameter!"); usage(); } // Now make a server object. new Server(port); } // The constructor for the server class Server(int port) { connections = new Vector(); // Create a server socket listening to that port. try { listener = new ServerSocket(port); } catch (java.io.IOException e) { System.out.print("Unable to bind to port "); System.out.print(port); System.out.println(". Perhaps that port is in use."); // Exit the application System.exit(0); } // Create the listening thread. listenerThread = new Thread(this); listenerThread.start(); } static void usage() { System.out.println("Usage: java talk.Server port#"); // Exit the application. System.exit(0); } public void run() { // The starting point for threads. Hand them off // to the appropriate methods. if (Thread.currentThread() == listenerThread) { listenerRun(); } } void listenerRun() { // Listen for new connections in an endless loop. while (true) { try { Socket s = listener.accept(); // Make a new Connection object to talk // to this person, and add it to our // collection. Connection c = new Connection(this, s); connections.addElement(c); } catch (java.io.IOException e) { // This particular connection // didn't quite make it. That's OK. } } } // Send a string received from one of the connections // to all of the rest. The string is not sent to the // connection it came from. void outputLine(Connection from, String s) { // Walk through all of the elements // in the connections Vector. Enumerations // are a pleasant way get at all of the // elements in a Vector or Hashtable. synchronized (connections) { Enumeration enum = connections.elements(); while (enum.hasMoreElements()) { Connection c = (Connection) enum.nextElement(); if (c != from) { c.inputLine(s); } } } } // Forget about the specified connection, which has closed. void forgetConnection(Connection c) { connections.removeElement(c); outputLine(null, "* * * " + c.name + " has disconnected."); } }