From 39e28eac9d274805d5b0bdc9f28583c16f65d50e Mon Sep 17 00:00:00 2001 From: imilne Date: Thu, 14 Dec 2006 11:56:17 +0000 Subject: [PATCH] Picking code updated with full basic implementation of message sending and server restart code. git-svn-id: https://svn.lifesci.dundee.ac.uk/svn/repository/trunk@255 be28352e-c001-0410-b1a7-c7978e42abec --- src/org/vamsas/client/picking/PickEndPoint.java | 98 ++++++++++++++--------- src/org/vamsas/client/picking/PickManager.java | 93 ++++++++++++++++++++- src/org/vamsas/client/picking/PickServer.java | 23 +++--- src/org/vamsas/client/picking/TestApp.java | 17 ++-- 4 files changed, 176 insertions(+), 55 deletions(-) diff --git a/src/org/vamsas/client/picking/PickEndPoint.java b/src/org/vamsas/client/picking/PickEndPoint.java index c81b744..7a464f1 100644 --- a/src/org/vamsas/client/picking/PickEndPoint.java +++ b/src/org/vamsas/client/picking/PickEndPoint.java @@ -6,72 +6,96 @@ import java.net.*; class PickEndPoint extends Thread { private Socket socket; + private int rPort; private BufferedWriter os; private BufferedReader in; + + private PickManager manager; - // Constructs a new client connection (client->server) - PickEndPoint() - throws Exception - { - // Attempt to connect... - // If we fail, wrapper has to attempt to make server instead?? - // Or keep trying until a server exists - socket = new Socket(InetAddress.getLocalHost(), PickServer.PORT); - - createStreams(); - } - - // Constructs a new client based on an existing connection (server->client) - PickEndPoint(Socket s) - throws IOException + PickEndPoint(PickManager manager, Socket s) { + this.manager = manager; socket = s; - createStreams(); } - private void createStreams() - throws IOException + boolean openConnection() { - os = new BufferedWriter(new OutputStreamWriter(socket.getOutputStream())); - - in = new BufferedReader(new InputStreamReader(socket.getInputStream())); + try + { + // Create the socket if it doesn't already exist + if (socket == null) + socket = new Socket(InetAddress.getLocalHost(), PickServer.PORT); + + rPort = socket.getPort(); + socket.setKeepAlive(true); + + // Open the streams for reading/writing + os = new BufferedWriter(new OutputStreamWriter(socket.getOutputStream())); + in = new BufferedReader(new InputStreamReader(socket.getInputStream())); - start(); + // Start the thread to listen for incoming messages + System.out.println("CLIENT: connection successful to port " + + socket.getPort() + " via port " + socket.getLocalPort()); + start(); + + return true; + } + catch (Exception e) + { + System.out.println("CLIENT: connection failed: " + e); + return false; + } } - void send() + void send(String str) { try { - System.out.println("CLIENT: sending message..."); - os.write("test message: " + (System.currentTimeMillis())); + System.out.println("CLIENT: send " + str + " to " + rPort); + os.write(str); // We use a newline to terminate the message os.newLine(); os.flush(); - System.out.println("CLIENT: message sent"); } catch (Exception e) { - System.out.println(e); + System.out.println("CLIENT: failed to send"); + + // TODO: terminate the connection on a failed send or retry? + terminate(); } } + // void receive() (threaded) public void run() { - try { - while (true) + try { - String str = in.readLine(); - - System.out.println("CLIENT: READ: " + str); + while (true) + { + String str = in.readLine(); + System.out.println("CLIENT: recv " + str + " from " + rPort); + + manager.handleMessage(this, str); + } + } + catch (Exception e) + { + // Means the other end of the connection has (probably died) so we need + // terminate this endpoint (if this is server side) + System.out.println("CLIENT: read failed: " + e); + + terminate(); } } - catch (Exception e) + + private void terminate() { - System.out.println("CLIENT: read fail: " + e); - // Means the other end of the connection has (probably died) so we need - // terminate this endpoint (if this is server side) - } + try { socket.close(); } + catch (IOException e) {} + + System.out.println("CLIENT: closing connection to port " + socket.getPort()); + manager.removeEndPoint(this); } } \ No newline at end of file diff --git a/src/org/vamsas/client/picking/PickManager.java b/src/org/vamsas/client/picking/PickManager.java index 6e93955..e4f4445 100644 --- a/src/org/vamsas/client/picking/PickManager.java +++ b/src/org/vamsas/client/picking/PickManager.java @@ -1,5 +1,6 @@ package org.vamsas.client.picking; +import java.net.*; import java.util.*; public class PickManager @@ -8,9 +9,99 @@ public class PickManager // a way of talking to either: // the server - if this is client side (and in which case, the list will only contain one element // the other clients - if this is server side - private LinkedList clients = new LinkedList(); + private LinkedList clients; + + private PickServer server; public PickManager() { + server = new PickServer(this); + clients = new LinkedList(); + + new InitializeThread().start(); + } + + // Called whenver we try to make a new endpoint<->endpoint connection + boolean addClientConnection(Socket socket) + { + PickEndPoint client = new PickEndPoint(this, socket); + + if (client.openConnection()) + { + clients.add(client); + System.out.println("List now contains " + clients.size() + " client(s)"); + return true; + } + + return false; + } + + public void sendMessage(String str) + { + forwardMessage(null, str); + } + + // Forwards (or sends) a message + // When the server receives a message, it will be resent to all clients, + // but *not* to the client that sent it out in the first place! + private void forwardMessage(PickEndPoint origin, String str) + { + ListIterator itor = clients.listIterator(); + while (itor.hasNext()) + { + PickEndPoint client = (PickEndPoint) itor.next(); + + if (client != origin) + client.send(str); + } + } + + // Called by the endpoint code when a message is received + // The manager has to: + // a) hand message to VAMSAS app + // b) forward it to other clients if we're the server + void handleMessage(PickEndPoint origin, String str) + { + if (server.isServer()) + forwardMessage(origin, str); + + // TODO: pass message to VAMSAS API + } + + void removeEndPoint(PickEndPoint client) + { + clients.remove(client); + System.out.println("List now contains " + clients.size() + " client(s)"); + + // If there's no endpoints left, then we've lost all connections and + // need to reinitialize + if (clients.size() == 0) + new InitializeThread().start(); + } + + private class InitializeThread extends Thread + { + public void run() + { + System.out.println("Initializing connection..."); + boolean connected = false; + + // Loop until we can get a connection (one way or the other) + while (!connected) + { + // Sleep for a rnd time so we don't end up with all the VAMSAS + // apps trying to initialize servers at the same time + try { Thread.sleep((int)Math.random()); } + catch (InterruptedException e) {} + + // Attempt to open the server port... + if (server.isServer() || server.createServer()) + connected = true; + + // If it fails, then attempt to make a client connection... + else if (addClientConnection(null)) + connected = true; + } + } } } \ No newline at end of file diff --git a/src/org/vamsas/client/picking/PickServer.java b/src/org/vamsas/client/picking/PickServer.java index f483b05..be18c67 100644 --- a/src/org/vamsas/client/picking/PickServer.java +++ b/src/org/vamsas/client/picking/PickServer.java @@ -8,11 +8,18 @@ class PickServer extends Thread static final int PORT = 53782; private ServerSocket serverSocket; + private boolean isServer = false; - PickServer() + private PickManager manager; + + PickServer(PickManager manager) { + this.manager = manager; } + boolean isServer() + { return isServer; } + boolean createServer() { try @@ -20,31 +27,29 @@ class PickServer extends Thread serverSocket = new ServerSocket(PORT); start(); - return true; + return isServer = true; } catch (IOException e) { // If we fail, just assume another app already has the port - System.out.println(e); + System.out.println("SERVER: " + e); return false; } } public void run() { - System.out.println("SERVER: listening..."); + System.out.println("SERVER: listening on " + PORT + " - SERVER"); // Loop forever, accepting connectons from other clients while (true) { try { - Socket socket = serverSocket.accept(); + Socket socket = serverSocket.accept(); + System.out.println("SERVER: connection detected"); - System.out.println("SERVER: connection made, spawning pipe..."); - - // Do something with the socket... - new PickEndPoint(socket); + manager.addClientConnection(socket); } catch (IOException e) {} } diff --git a/src/org/vamsas/client/picking/TestApp.java b/src/org/vamsas/client/picking/TestApp.java index 3e89ee8..507daea 100644 --- a/src/org/vamsas/client/picking/TestApp.java +++ b/src/org/vamsas/client/picking/TestApp.java @@ -7,16 +7,17 @@ public class TestApp { TestApp app = new TestApp(); - PickServer server = new PickServer(); + PickManager manager = new PickManager(); - - if (server.createServer() == false) - { - PickEndPoint client = new PickEndPoint(); + // Send 5 test messages... +// for (int i = 0; i < 5; i++) + while (true) + { + try { Thread.sleep((int) (Math.random()*20000)); } + catch (InterruptedException e) {} - for (int i = 0; i < 10; i++) - client.send(); -// client.send(); + int rnd = (int) (Math.random()*100); + manager.sendMessage("" + rnd); } } -- 1.7.10.2