aboutsummaryrefslogtreecommitdiff
path: root/src/IvyClient.java
diff options
context:
space:
mode:
authorjestin2002-06-07 11:18:02 +0000
committerjestin2002-06-07 11:18:02 +0000
commitbe2d18b332eb74b6529e18a8f10abf71fcd7382a (patch)
tree66a3cd8752422dc63ee5ddfeb781c11ec4879212 /src/IvyClient.java
parent56bad1fac964a8562ef46fa995766e9e28173dc5 (diff)
downloadivy-java-be2d18b332eb74b6529e18a8f10abf71fcd7382a.zip
ivy-java-be2d18b332eb74b6529e18a8f10abf71fcd7382a.tar.gz
ivy-java-be2d18b332eb74b6529e18a8f10abf71fcd7382a.tar.bz2
ivy-java-be2d18b332eb74b6529e18a8f10abf71fcd7382a.tar.xz
doc change for the new release
Diffstat (limited to 'src/IvyClient.java')
-rwxr-xr-xsrc/IvyClient.java188
1 files changed, 138 insertions, 50 deletions
diff --git a/src/IvyClient.java b/src/IvyClient.java
index 18a50f2..3857631 100755
--- a/src/IvyClient.java
+++ b/src/IvyClient.java
@@ -20,8 +20,14 @@ import gnu.regexp.*;
*
* CHANGELOG:
* 1.0.12:
+ * - introducing a Ping and Pong in the protocol, in order to detect the loss of
+ * connection faster. Enabled through the use of -DIVY_PING variable only
+ * the PINGTIMEOUT value in milliseconds allows me to have a status of the
+ * socket guaranteed after this timeout
* - right handling of IOExceptions in sendBuffer, the Client is removed from
- * the bus
+ * the bus
+ * - sendDie goes public, so does sendDie(String)
+ * - appName visibility changed from private to protected
* 1.0.10:
* - removed the timeout bug eating all the CPU resources
*/
@@ -38,10 +44,14 @@ public class IvyClient implements Runnable {
final static int SchizoToken = 6; /* avoid race condition in concurrent connexions */
final static int DirectMsg = 7;/* the peer sends a direct message */
final static int Die = 8; /* the peer wants us to quit */
+ final static int Ping = 9; /* checks the presence of the other */
+ final static int Pong = 10; /* checks the presence of the other */
+
final static String MESSAGE_TERMINATOR = "\n"; /* the next protocol will use \r */
final static String StartArg = "\u0002";/* begin of arguments */
final static String EndArg = "\u0003"; /* end of arguments */
+
private static boolean debug = (System.getProperty("IVY_DEBUG")!=null) ;
private Ivy bus;
private Socket socket;
@@ -49,19 +59,25 @@ public class IvyClient implements Runnable {
private OutputStream out;
private Hashtable regexp_in = new Hashtable();
private Hashtable regexp_text = new Hashtable();
- private String appName;
private int appPort;
- private boolean gardefou=true;
private boolean peerCalling;
- private Thread client;
+ private volatile Thread clientThread;// volatile to ensure the quick communication
+ private Integer clientKey ;
+ private static boolean doping = (System.getProperty("IVY_PING")!=null) ;
+ final static int PINGTIMEOUT = 5000;
+ private PINGER pinger;
+ private volatile Thread pingerThread;
+
+ // protected variables
+ String appName;
- IvyClient(Ivy bus, Socket socket,boolean peerCalling) throws IOException {
+ IvyClient(Ivy bus, Socket socket,boolean peerCalling,Integer clientKey) throws IOException {
appName = "Unknown";
appPort = 0;
this.bus = bus;
this.socket = socket;
this.peerCalling=peerCalling;
- // CHANGE: socket.setSoTimeout(100);
+ this.clientKey=clientKey;
in = new BufferedReader(new InputStreamReader(socket.getInputStream()));
out = socket.getOutputStream();
Hashtable regexps=bus.regexp_out;
@@ -72,14 +88,19 @@ public class IvyClient implements Runnable {
send(SchizoToken,bus.applicationPort,bus.appName);
// sends our regexps to the peer
for (Enumeration e = regexps.keys(); e.hasMoreElements(); ) {
- Integer key = (Integer)e.nextElement();
- sendRegexp( key.intValue(),(String)regexps.get(key));
+ Integer ikey = (Integer)e.nextElement();
+ sendRegexp( ikey.intValue(),(String)regexps.get(ikey));
}
send( EndRegexp,0,"");
// spawns a thread to manage the incoming traffic on this
// socket. We should be ready to receive messages now.
- client= new Thread(this);
- client.start();
+ clientThread = new Thread(this);
+ clientThread .start();
+ if (doping) {
+ pinger = new PINGER();
+ pingerThread=new Thread(pinger);
+ pingerThread.start();
+ }
}
/**
@@ -87,6 +108,8 @@ public class IvyClient implements Runnable {
*/
public String getApplicationName() { return appName ; }
+ Integer getClientKey() { return clientKey ; }
+
/**
* allow an Ivy package class to access the list of regexps at a
* given time.
@@ -98,7 +121,7 @@ public class IvyClient implements Runnable {
int getAppPort() { return appPort ; }
void sendRegexp(int id,String regexp) {
- send(AddRegexp,id,regexp); /* perhaps we should perform some checking here */
+ send(AddRegexp,id,regexp); /* perhaps we should perform some checking here */
}
public void delRegexp(int id) {send( DelRegexp,id,"");}
@@ -124,14 +147,23 @@ public class IvyClient implements Runnable {
/**
* closes the connexion to the peer.
- * @param msg the debug information
+ * @param notify should I send Bye message ?
* the thread managing the socket is stopped
*/
- void close(String msg) throws IOException {
- traceDebug("(closing) "+msg);
- gardefou=false;
- client.interrupt();
- // socket.close(); // should I ?
+ void close(boolean notify) throws IOException {
+ traceDebug("closing connexion to "+appName);
+ if (doping) { pinger.stopPinging(); }
+ if (notify) sendBye("hasta la vista");
+ stopListening();
+ // bus.clientDisconnect(this);
+ socket.close(); // should I also close in and out ?
+ }
+
+ void stopListening() {
+ Thread t = clientThread;
+ if (t==null) return; // we can be summoned to quit from two path at a time
+ clientThread=null;
+ t.interrupt();
}
/**
@@ -149,31 +181,27 @@ public class IvyClient implements Runnable {
* the code of the thread handling the incoming messages.
*/
public void run() {
+ Thread thisThread = Thread.currentThread();
+ traceDebug("Connected from "+ socket.getInetAddress().getHostName()+ ":"+socket.getPort());
String msg = null;
- try {
- traceDebug("Connected from "+ socket.getInetAddress().getHostName()+ ":"+socket.getPort());
- while ( gardefou ) {
- try {
- if ((msg=in.readLine()) != null ) {
- newParseMsg(msg);
- }
- } catch (IvyException ie) {
- ie.printStackTrace();
- } catch (InterruptedIOException ioe) {
- System.out.println("I have been interrupted. I'm about to leave my thread loop");
- if (!gardefou) break;
+ while ( clientThread==thisThread ) {
+ try {
+ if ((msg=in.readLine()) != null ) {
+ if (doping && (pingerThread!=null)) pingerThread.interrupt();
+ newParseMsg(msg);
}
+ } catch (IvyException ie) {
+ ie.printStackTrace();
+ } catch (InterruptedIOException ioe) {
+ System.out.println("I have been interrupted. I'm about to leave my thread loop");
+ if (thisThread!=clientThread) break;
+ } catch (IOException e) {
+ if (clientThread!=thisThread) break;
+ traceDebug("abnormally Disconnected from "+
+ socket.getInetAddress().getHostName()+":"+socket.getPort());
}
- traceDebug("normally Disconnected from "+ socket.getInetAddress().getHostName()+":"+socket.getPort());
- socket.close();
- out.close();
- in.close();
- } catch (IOException e) {
- traceDebug("abnormally Disconnected from "+
- socket.getInetAddress().getHostName()+":"+socket.getPort());
- }
- bus.disconnect(this);
- bus.removeClient(this);
+ } // while
+ traceDebug("normally Disconnected from "+ appName);
}
private void sendBuffer( String buffer ) throws IvyException {
@@ -183,8 +211,12 @@ public class IvyClient implements Runnable {
out.flush();
} catch ( IOException e ) {
traceDebug("I can't send my message to this client. He probably left");
+ // first, I'm not a first class IvyClient any more
+ bus.removeClient(this);
+ // invokes the die applicationListeners
+ bus.disconnectReceived(this);
try {
- close("IO Exception");
+ close(false);
} catch (IOException ioe) {
throw new IvyException("close failed"+ioe.getMessage());
}
@@ -258,9 +290,32 @@ public class IvyClient implements Runnable {
}
from=to+1;
switch (msgType) {
+ case Die:
+ traceDebug("received die Message from " + appName);
+ // first, I'm not a first class IvyClient any more
+ bus.removeClient(this);
+ // invokes the die applicationListeners
+ bus.dieReceived(this,msgId.intValue());
+ // makes the bus die
+ bus.stop();
+ try {
+ close(false);
+ } catch (IOException ioe) {
+ throw new IvyException(ioe.getMessage());
+ }
+ break;
case Bye:
- bus.die(this,msgId.intValue());
- gardefou=false;
+ // the peer quits
+ traceDebug("received bye Message from "+appName);
+ // first, I'm not a first class IvyClient any more
+ bus.removeClient(this);
+ // invokes the die applicationListeners
+ bus.disconnectReceived(this);
+ try {
+ close(false);
+ } catch (IOException ioe) {
+ throw new IvyException(ioe.getMessage());
+ }
break;
case AddRegexp:
String regexp=s.substring(from,b.length);
@@ -305,6 +360,16 @@ public class IvyClient implements Runnable {
}
bus.callCallback(this,msgId,tab);
break;
+ case Pong:
+ String paramPong=s.substring(from,b.length);
+ traceDebug("Ping msg from "+appName+" : "+paramPong);
+ break;
+ case Ping:
+ // I receive a ping. I can answer a pong.
+ String param=s.substring(from,b.length);
+ traceDebug("Ping msg from "+appName+" : "+param);
+ sendPong(param);
+ break;
case Error:
String error=s.substring(from,b.length);
traceDebug("Error msg "+msgId+" "+error);
@@ -314,7 +379,7 @@ public class IvyClient implements Runnable {
appPort=msgId.intValue();
if ( bus.checkConnected(this) ) {
try {
- close("Quitting Application already connected");
+ close(false);
} catch (IOException ioe) {
throw new IvyException("io " + ioe.getMessage());
}
@@ -325,20 +390,43 @@ public class IvyClient implements Runnable {
String direct=s.substring(from,b.length);
bus.directMessage( this, msgId.intValue(), direct );
break;
- case Die:
- gardefou=false;
- bus.die(this,msgId.intValue());
- break;
default:
throw new IvyException("protocol error, unknown message type "+msgType);
}
}
- private void sendDie() {send(Die,0,"");}
- private void sendDie(String message) {send(Die,0,message);}
+ void sendPong(String s) {send(Pong,0,s);}
+ void sendPing(String s) {send(Ping,0,s);}
+
+ private void sendBye() {send(Bye,0,"");}
+ private void sendBye(String message) {send(Bye,0,message);}
+
+ public void sendDie() { send(Die,0,""); }
+ public void sendDie(String message) {send(Die,0,message);}
+
private InetAddress getRemoteAddress() { return socket.getInetAddress(); }
+
+ public String toString() {
+ return "IvyClient "+bus.appName+":"+appName;
+ }
private void traceDebug(String s){
- if (debug) System.out.println("-->IvyClient "+appName+"<-- "+s);
+ if (debug) System.out.println("-->IvyClient "+bus.appName+":"+appName+"<-- "+s);
+ }
+
+ class PINGER implements Runnable {
+ boolean isPinging = false;
+ public void run() {
+ isPinging=true;
+ while (isPinging) {
+ try {
+ Thread.sleep(PINGTIMEOUT);
+ sendPing("are you here ?");
+ } catch (InterruptedException ie) {
+ }
+ }
+ }
+ public void stopPinging() { isPinging=false; pingerThread.interrupt();}
}
+
} // class IvyClient
/* EOF */