001    /*
002     * Generic Server Application
003     * $Id: Server.java,v 1.1.1.1 2002/06/05 21:56:32 root Exp $
004     *
005     * Developed for "Rethinking CS101", a project of Lynn Andrea Stein's AP Group.
006     * For more information, see <a href="http://www.ai.mit.edu/projects/cs101/">the
007     * CS101 homepage</a> or email <las@ai.mit.edu>.
008     *
009     * Copyright (C) 1996 Massachusetts Institute of Technology.
010     * Please do not redistribute without obtaining permission.
011     */
012    
013    package cs101.net;
014    
015    import cs101.awt.ServerDialog;
016    import java.net.*;
017    import java.io.*;
018    import java.util.*;
019    
020    /**
021     * Generic Server class:  broadcasts whatever messages it receives to
022     * all clients other than the message's originator.  Spawns one thread to
023     * listen and multiple others to handle the clients as they connect.
024     * <p>
025     * Takes a single optional argument to specify the port. Otherwise
026     * spawns a UI dialog to get connection information from the user.
027     * <p>
028     * Some hints taken from ORA Servers.
029     * <p>
030     * Copyright 1996 Massachusetts Institute of Technology
031     *
032     * @see      cs101.net.RunServer
033     * @see      cs101.net.Client
034     * @see      cs101.awt.ServerDialog
035     *
036     * @author   Todd C. Parnell, tparnell@ai.mit.edu
037     * @author   Maciej Stachowiak, maciej@ai.mit.edu
038     * @author   Emil Sit, sit@mit.edu
039     * @author   Joshua Reuben Brown, reuben@ai.mit.edu
040     * @author   Lynn Andrea Stein, las@ai.mit.edu
041     * @version  $Id: Server.java,v 1.1.1.1 2002/06/05 21:56:32 root Exp $
042     *
043     */
044    public class Server implements Runnable {
045    
046      /** the server socket, i.e., the listener */
047      protected ServerSocket sock;
048    
049      /** list of BabySitters to handle each client connection  */
050      protected Vector babySitters;
051    
052      /** animating Thread */
053      protected Thread spirit;
054    
055      /**
056       * Creates a server socket.  Waits for connections.
057       * No argument version prompts users for port information.
058       */
059      public Server () {
060        ServerDialog sd = new ServerDialog();
061        sd.ask();
062        this.listenOn( sd.getPort() );
063      }
064    
065      /**
066       * Creates a server socket.  Waits for connections.
067       *
068       * @param port   The integer representing the port number to listen on.
069       */
070      public Server( int port ) {
071        this.listenOn( port );
072      }
073    
074      /**
075       * Helper method to actually open the ServerSocket and intialize
076       * other state.  Also spawns Thread to continue listening.  Called
077       * internally. 
078       *
079       * @param port   The integer representing the port number to listen on.
080       */
081      protected void listenOn( int port ) {
082        System.out.println("Server:  starting up on port " + port );
083        try {
084          this.sock = new ServerSocket( port );
085        } catch (IOException e) {
086          throw new RuntimeException("Server:  failed to listen on port "
087    + port );
088        }
089        this.babySitters = new Vector();
090        this.spirit = new Thread( this );
091        this.spirit.start();
092      }
093    
094      /**
095       * Wait loop to service the ServerSocket.  Called by this server's
096       * Thread.  Should not be called externally.
097       * Each time that  a connection is recieved, forks a BabySitter to 
098       * handle that connection.
099       */
100      public void run() {
101        try {
102          while ( true ) {
103            System.out.println("Server:  listening for a connection");
104            this.spawnBabySitter( this.sock.accept() );
105          }
106        } catch (IOException e) {
107          System.out.println( "Server:  abrupt failure on accept attempt." );
108          System.out.println( "Server:  no longer accepting connections." );
109        }
110      }
111        
112      /**
113       * Removes a BabySitter for the list of babySitters.
114       * 
115       * @param bbst the BabySitter to be remooved from use.
116       */
117      protected void removeBabySitter(BabySitter bbst) {
118        this.babySitters.removeElement(bbst);
119        bbst.stop();
120      }
121    
122      /** 
123       * Creates a BabySitter with the client socket passed and
124       * adds it to the list of BabySitters.
125       *
126       * @param s the client socket that this BabySitter will handle
127       */
128      protected void spawnBabySitter(Socket s) {
129        BabySitter bbst=new BabySitter(s, this);
130        babySitters.addElement(bbst);
131      }
132    
133      /**
134       * Sends the string passed in to all clients accept the one
135       * represented by the BabySitter passed in.
136       *
137       * @param s the string to send
138       * @param bbst the BabySitter that handle the client that we don't want to 
139       *           send to (the client that the message came from).
140       */
141      protected void sendToAllExcept(String s, BabySitter bbst) {
142        for(Enumeration e=babySitters.elements();e.hasMoreElements();) {
143          BabySitter current = (BabySitter) e.nextElement();
144          if (current != bbst) {
145            current.send(s);
146          }
147        }
148      }
149    }
150    
151    /* Comments:
152     *
153     * History:
154     *     $Log: Server.java,v $
155     *     Revision 1.1.1.1  2002/06/05 21:56:32  root
156     *     CS101 comes to Olin finally.
157     *
158     *     Revision 1.5  1998/07/24 17:13:45  tparnell
159     *     Placate new javadoc behavior
160     *
161     *     Revision 1.4  1998/07/22 18:18:07  tparnell
162     *     move from util to net
163     *
164     *     Revision 1.3  1998/06/24 16:18:24  tparnell
165     *     more revisions from summer98
166     *
167     *     Revision 1.2  1998/06/03 21:32:08  tparnell
168     *     conversion from Java 1.0 to 1.1
169     *
170     *     Revision 1.6  1996/11/18 17:10:24  las
171     *     All files appear to be working.  Some of the files in this directory
172     *     belong in cs101.util.  These will be moved Real Soon Now.  Also, added
173     *     ClientMonitor, which watches net traffic but doesn't send.
174     *
175     *     Revision 1.5  1996/11/18 16:41:21  las
176     *     Client, Server, their dependencies (e.g. the Dialogs and their
177     *     invokers) all work.  ClientTester is a bit awkward in that it doesn't
178     *     echo received strings until something is read.  Oh, well.
179     *     Moving them to cs101.util in the next revision.
180     *
181     *     Revision 1.4  1996/11/17 22:28:16  las
182     *     Everything compiles (now).  Client, Server, ClientDialog, ServerDialog,
183     *     StringHandler, and RunServer need to be moved to cs101.util.  But
184     *     first, to test....
185     *
186     *     Revision 1.3  1996/11/17 20:43:19  las
187     *     Server, RunServer written, not tested.  Need to be moved to
188     *     cs101.util....
189     *
190     *     Revision 1.2  1996/11/17 20:37:38  las
191     *     Server is written, but not yet tested.  Should be used with RunServer.java.
192     *
193     *     Revision 1.1  1996/11/17 19:39:33  las
194     *     Intermediate state on the way to an application version.  Some files
195     *     here actually belong in CS101.  Otherwise, the general file structure
196     *     is correct, but the file contents are in some cases grossly out of
197     *     line.
198     *
199     *     Desired structure:
200     *     SharedWhiteboardDemo runs the (client side of the) demo.
201     *     SharedWhiteboard is a helper file that starts things up correctly;
202     *     it's the class definition, though, not the main (which is in
203     *     SharedWhiteboardDemo).
204     *     NetScribbleData is ScribbleData that sets up a client connection.  It
205     *     uses StringHandler and Client.
206     *     StringHandler, ClientDialog, ServerDialog, and maybe Client and Server
207     *     go in the cs101 package.  StringHandler is the interface Client uses.
208     *     ClientDialog and ServerDialog are QueryDialogs specialized for
209     *     obtaining the appropriate information.  Client and Server are pretty
210     *     generic (Server is a broadcaster and Client has send and
211     *     StringHandler.handleString.)
212     *     Fall 96, they write SharedWhiteboard(Demo), NetScribbleData, and
213     *     Client.
214     *
215     *     Revision 1.5  1996/08/01 18:26:31  reuben
216     *     More javadoc tweaking (hopefully the final pass)
217     *
218     *     Revision 1.4  1996/08/01 01:56:34  reuben
219     *     Yesturday's changes were tested.
220     *     (I wonder if using cvs and $log$ creates a circular modifcation problem)
221     *
222     *     Revision 1.3  1996/07/30 17:26:00  reuben
223     *     Added/corrected javadoc comments.
224     *
225     *     Revision 1.2  1996/07/23 21:10:38  reuben
226     *     Moved Colorfield and DisplayField to cs101.util package.
227     *     Made the necessary changes to PNC.
228     *     Compiled and tested all 4 demos.
229     *
230     *     Revision 1.1.1.1  1996/07/18 17:38:24  sit
231     *     Import from /mit/6.096/share/classes after 6.80s session
232     *
233     *     Revision 1.1  1996/07/02 21:47:51  las
234     *     Initial revision
235     *
236     */
237