/* * ManyServer * Copyright(c) 1996 Jaripekka Salminen * * The general idea was taken from * Multiserver by Jeff Breidenbach, * which is based on Example 9-3 in Java in * a Nutshell by David Flanagan. * * This is a simplified implementation of the same thing. * * Any message sent to ManyServer will be broadcast to all clients * on the same channel. The clients may interpret the messages * any way they want. * * The following messages are interpreted as server side commands: * * CHANNEL * * HISTORY * * Version Alpha 1, Sep 1996 * - channels * - history * */ import java.io.*; import java.net.*; import java.util.*; public class ManyServer { public ManyServer(int port) { ServerSocket serverSocket = null; try { serverSocket = new ServerSocket(port); while (true) { try { Socket newSocket = serverSocket.accept(); SingleServer newServer = new SingleServer(newSocket); Thread newThread = new Thread(newServer); newThread.start(); } catch (Exception e) { System.out.println("Error with the new socket stuff : " + e); } } } catch (Exception e) { System.out.println("Error with the socket stuff : " + e); } finally { if (serverSocket != null) { try { serverSocket.close(); } catch ( IOException e ) { System.out.println("Error with socket close : " + e); } } System.exit(1); } } public static void main( String args[] ) { if ( args.length != 1 ) { System.out.println("Usage: java ManyServer port"); } int serverPort = Integer.parseInt(args[0]); ManyServer manyServer = new ManyServer(serverPort); } } class SingleServer implements Runnable { static Vector serverVector = null; static Vector historyVector = null; static final int MAX_HISTORY = 200; Socket mySocket; DataInputStream inputs; DataOutputStream outputs; boolean alive = false; String channel = null; public SingleServer( Socket _mySocket ) { if ( serverVector == null ) { serverVector = new Vector(); } if ( historyVector == null ) { historyVector = new Vector(); } addtoServerVector(this); alive = true; mySocket = _mySocket; channel = "Default"; } synchronized void addtoServerVector(Object obj) { serverVector.addElement(obj); } synchronized void cleanServerVector() { SingleServer oneServer; for ( int i = 0; i < serverVector.size(); i++ ) { oneServer = (SingleServer) serverVector.elementAt(i); if (!oneServer.alive) { serverVector.removeElementAt(i); i--; } } } synchronized void addtoHistory(String mess, String chan) { if ( historyVector.size() >= MAX_HISTORY ) { historyVector.removeElementAt(0); } historyVector.addElement(new HistoryEvent(mess,chan)); } synchronized void dumpHistory() { HistoryEvent historyEvent; for ( int i = 0; i < historyVector.size(); i++ ) { try { historyEvent = (HistoryEvent)historyVector.elementAt(i); if ( historyEvent != null ) { if (historyEvent.channel.equals(this.channel)) { if ( historyEvent.message != null ) { this.write( (String) historyEvent.message ); } } } } catch (Exception e) { } } } public void run () { String message; try { inputs = new DataInputStream(mySocket.getInputStream()); outputs = new DataOutputStream(mySocket.getOutputStream()); boolean go = true; while (go) { message = inputs.readLine(); if ( message == null ) { go = false; } else { System.out.println(message); if (message.startsWith("CHANNEL ")) { channel = message.substring(8); } else if (message.startsWith("HISTORY")) { dumpHistory();} else if (message.startsWith(".lopp")){ System.exit(1);} else { cleanServerVector(); manyCast(message); addtoHistory(message,this.channel); } } } inputs.close(); outputs.close(); mySocket.close(); } catch (Exception e) { alive = false; } } public synchronized void write ( String mess ) { try { outputs.writeBytes(mess+"\n"); outputs.flush(); } catch (Exception e) { alive = false; } } public void manyCast( String mess ) { SingleServer oneServer; System.out.println("manyCast to " + serverVector.size() + " servers."); for ( int i = 0; i < serverVector.size(); i++ ) { oneServer = (SingleServer) serverVector.elementAt(i); if (oneServer.channel.equals(this.channel)) { oneServer.write(mess); } } } } class HistoryEvent { String message; String channel; public HistoryEvent(String _message, String _channel) { message = _message; channel = _channel; } }