/* * XClient.java -- * * Copyright 1996 Regents of the University of California * Permission to use, copy, modify, and distribute this * software and its documentation for any purpose and without * fee is hereby granted, provided that this copyright * notice appears in all copies. The University of California * makes no representations about the suitability of this * software for any purpose. It is provided "as is" without * express or implied warranty. * * rcsid = "$Header: /disks/barad-dur/now/rywang/src/java/classes/ryw/XAnim.java,v 1.1 1995/10/07 14:15:40 rywang Exp $ xFS (Berkeley)" */ package ryw; import java.lang.*; import java.net.*; import java.io.*; /** * A client object that connects, reads, and writes from a server * in a thread. */ public abstract class XClient implements Runnable { String host; int port; int retryInter; Thread listener; Socket server; protected InputStream ins; protected OutputStream outs; protected DataInputStream dins; protected DataOutputStream douts; protected PrintStream pouts; protected boolean connected; public synchronized void connect (String host, int port) throws IOException { XError.info ("XClient:connect:to "+host+" at "+port); this.host = host; this.port = port; stop (); server = new Socket (host, port); ins = server.getInputStream (); dins = new DataInputStream (ins); outs = server.getOutputStream (); douts = new DataOutputStream (outs); pouts = new PrintStream (outs); connected = true; start (); XError.info ("XClient:connection established"); } public synchronized void reset () { try { if (server != null) { server.close (); server = null; } connected = false; if (ins != null) { ins.close (); ins = null; dins = null; } if (outs != null) { outs.close (); outs = null; douts = null; } } catch (Exception e) { } } public synchronized void tryConnect (String host, int port, int retryInter) { this.retryInter = retryInter; for (;;) { try { connect (host, port); break; } catch (Exception e) { XError.yell ("XClient:tryConnect: failed to connect"); try { Thread.sleep (retryInter); } catch (Exception e2) { } XError.info ("XClient:tryConnect: retrying..."); } } } public synchronized void tryReconnect () { tryConnect (host, port, retryInter); } public synchronized void start () { if (listener == null) { if (!connected) tryReconnect (); listener = new Thread (this); listener.start (); } } public synchronized void stop () { connected = false; if (listener == null) { return; } listener.stop (); listener = null; reset (); } public void run () { for (;;) { try { readFromServer (); } catch (ThreadDeath e) { XError.say ("XClient:run: thread death"); throw e; } catch (IOException e) { if (connected) { XError.yell (e, "XClient:run: readFromServer failed"); tryConnect (host, port, retryInter); } } catch (NullPointerException e) { /* * When I kill this thread, I'm supposed to * get ThreadDeath, but instead I get * NullPointer from readFromServer(). */ XError.say ("XClient:run: null pointer, thread stopped"); throw new ThreadDeath (); } } } public synchronized void sendLoop () { for (;;) { try { sendToServer (); } catch (IOException e) { XError.yell (e, "XClient:sendLoop: sendToServer failed"); tryConnect (host, port, retryInter); } } } public abstract void readFromServer () throws IOException; public abstract void sendToServer () throws IOException; }