www.pudn.com > jnp-src.rar > GenericClient.java


/*
 * Java Network Programming, Second Edition
 * Merlin Hughes, Michael Shoffner, Derek Hamner
 * Manning Publications Company; ISBN 188477749X
 *
 * http://nitric.com/jnp/
 *
 * Copyright (c) 1997-1999 Merlin Hughes, Michael Shoffner, Derek Hamner;
 * all rights reserved; see license.txt for details.
 */

import java.io.*; 
import java.net.*; 
import java.util.*; 
 
public class GenericClient extends Thread { 
  static private int clientNumber; 
  static private synchronized int nextClientNum () { return clientNumber ++; } 
   
  protected Queue queue; 
  protected Hashtable registry; 
  protected MessageOutput messageOut; 
 
  public GenericClient (String host, int port, String name) 
    throws IOException { 
    super ("GenericClient-" + nextClientNum ()); 
    connect (host, port); 
    logon (name); 
    registry = new Hashtable (); 
    queue = new Queue (); 
    QueueOutputStream queueOut = new QueueOutputStream (queue); 
    messageOut = new RoutingOutputStream (queueOut); 
  } 
 
  protected InputStream in; 
  protected OutputStream out; 
   
  protected void connect (String host, int port) throws IOException { 
    Socket socket = new Socket (host, port); 
    in = socket.getInputStream (); 
    out = socket.getOutputStream (); 
  } 
 
  protected void logon (String name) throws IOException { 
    try { 
      DataOutputStream dataOut = new DataOutputStream (out); 
      dataOut.writeUTF (name); 
      dataOut.flush (); 
      DataInputStream dataIn = new DataInputStream (in); 
      boolean registered = dataIn.readBoolean (); 
      if (!registered) 
        throw new IOException ("Name in use"); 
    } catch (IOException ex) { 
      try { 
        out.close (); 
      } catch (IOException ignored) { 
      } 
      throw ex; 
    } 
  } 
 
  protected boolean finished; 
   
  public void shutdown () throws IOException { 
    finished = true; 
    interrupt (); 
    out.close (); 
  } 
 
  public void run () { 
    QueueInputStream queueIn = new QueueInputStream (queue); 
    MessageOutputStream messageOut = new MessageOutputStream (out); 
    GenericMessageCopier copier = 
      new GenericMessageCopier (this, queueIn, messageOut); 
    try { 
      copier.start (); 
      demux (); 
    } catch (IOException ex) { 
      if (!finished) 
        ex.printStackTrace (); 
    } finally { 
      copier.finish (); 
      closedown (); 
    } 
  } 
 
  protected void demux () throws IOException { 
    MessageInputStream messageIn = new MessageInputStream (in); 
    MultiplexInputStream multiplexIn = new MultiplexInputStream (messageIn); 
    while (!Thread.interrupted ()) { 
      multiplexIn.receive (); 
      Client client = (Client) registry.get (multiplexIn.getLabel ()); 
      if (client != null) { 
        try { 
          client.receive (new DataInputStream (multiplexIn)); 
        } catch (RuntimeException ex) { 
          ex.printStackTrace (); 
        } 
      } 
    } 
  } 
 
  protected void closedown () { 
    try { 
      out.close (); 
    } catch (IOException ex) { 
      ex.printStackTrace (); 
    } 
    synchronized (registry) { 
      Enumeration clients = registry.keys (); 
      while (clients.hasMoreElements ()) { 
        deregister ((String) clients.nextElement ()); 
      } 
    } 
  } 
 
  public void register (String label, Client client) { 
    synchronized (registry) { 
      deregister (label); 
      registry.put (label, client); 
      client.setMessageOutput 
        (new MultiplexOutputStream (messageOut, label)); 
    } 
  } 
 
  public void deregister (String label) { 
    synchronized (registry) { 
      Client client = (Client) registry.remove (label); 
      if (client != null) 
        client.disconnected (); 
    } 
  } 
}