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