class PickEndPoint extends Thread\r
{\r
private Socket socket;\r
+ private int rPort;\r
private BufferedWriter os;\r
private BufferedReader in;\r
+\r
+ private PickManager manager; \r
\r
- // Constructs a new client connection (client->server)\r
- PickEndPoint()\r
- throws Exception\r
- {\r
- // Attempt to connect...\r
- // If we fail, wrapper has to attempt to make server instead??\r
- // Or keep trying until a server exists\r
- socket = new Socket(InetAddress.getLocalHost(), PickServer.PORT);\r
- \r
- createStreams();\r
- }\r
- \r
- // Constructs a new client based on an existing connection (server->client)\r
- PickEndPoint(Socket s)\r
- throws IOException\r
+ PickEndPoint(PickManager manager, Socket s)\r
{\r
+ this.manager = manager;\r
socket = s;\r
- createStreams();\r
}\r
\r
- private void createStreams()\r
- throws IOException\r
+ boolean openConnection()\r
{\r
- os = new BufferedWriter(new OutputStreamWriter(socket.getOutputStream()));\r
- \r
- in = new BufferedReader(new InputStreamReader(socket.getInputStream()));\r
+ try\r
+ {\r
+ // Create the socket if it doesn't already exist\r
+ if (socket == null)\r
+ socket = new Socket(InetAddress.getLocalHost(), PickServer.PORT);\r
+ \r
+ rPort = socket.getPort();\r
+ socket.setKeepAlive(true);\r
+ \r
+ // Open the streams for reading/writing\r
+ os = new BufferedWriter(new OutputStreamWriter(socket.getOutputStream()));\r
+ in = new BufferedReader(new InputStreamReader(socket.getInputStream()));\r
\r
- start();\r
+ // Start the thread to listen for incoming messages\r
+ System.out.println("CLIENT: connection successful to port "\r
+ + socket.getPort() + " via port " + socket.getLocalPort());\r
+ start();\r
+ \r
+ return true;\r
+ }\r
+ catch (Exception e)\r
+ {\r
+ System.out.println("CLIENT: connection failed: " + e);\r
+ return false;\r
+ }\r
}\r
\r
- void send()\r
+ void send(String str)\r
{\r
try\r
{\r
- System.out.println("CLIENT: sending message...");\r
- os.write("test message: " + (System.currentTimeMillis()));\r
+ System.out.println("CLIENT: send " + str + " to " + rPort);\r
+ os.write(str);\r
\r
// We use a newline to terminate the message\r
os.newLine();\r
os.flush();\r
- System.out.println("CLIENT: message sent");\r
}\r
catch (Exception e)\r
{\r
- System.out.println(e);\r
+ System.out.println("CLIENT: failed to send");\r
+ \r
+ // TODO: terminate the connection on a failed send or retry?\r
+ terminate();\r
}\r
}\r
\r
+ // void receive() (threaded)\r
public void run()\r
{\r
- try {\r
- while (true)\r
+ try\r
{\r
- String str = in.readLine();\r
- \r
- System.out.println("CLIENT: READ: " + str);\r
+ while (true)\r
+ {\r
+ String str = in.readLine(); \r
+ System.out.println("CLIENT: recv " + str + " from " + rPort);\r
+ \r
+ manager.handleMessage(this, str);\r
+ }\r
+ }\r
+ catch (Exception e)\r
+ {\r
+ // Means the other end of the connection has (probably died) so we need\r
+ // terminate this endpoint (if this is server side)\r
+ System.out.println("CLIENT: read failed: " + e);\r
+ \r
+ terminate();\r
}\r
}\r
- catch (Exception e)\r
+ \r
+ private void terminate()\r
{\r
- System.out.println("CLIENT: read fail: " + e);\r
- // Means the other end of the connection has (probably died) so we need\r
- // terminate this endpoint (if this is server side)\r
- }\r
+ try { socket.close(); }\r
+ catch (IOException e) {}\r
+ \r
+ System.out.println("CLIENT: closing connection to port " + socket.getPort());\r
+ manager.removeEndPoint(this);\r
}\r
}
\ No newline at end of file
package org.vamsas.client.picking;\r
\r
+import java.net.*;\r
import java.util.*;\r
\r
public class PickManager\r
// a way of talking to either:\r
// the server - if this is client side (and in which case, the list will only contain one element\r
// the other clients - if this is server side\r
- private LinkedList clients = new LinkedList();\r
+ private LinkedList clients;\r
+ \r
+ private PickServer server;\r
\r
public PickManager()\r
{\r
+ server = new PickServer(this);\r
+ clients = new LinkedList();\r
+ \r
+ new InitializeThread().start();\r
+ }\r
+ \r
+ // Called whenver we try to make a new endpoint<->endpoint connection\r
+ boolean addClientConnection(Socket socket)\r
+ {\r
+ PickEndPoint client = new PickEndPoint(this, socket);\r
+ \r
+ if (client.openConnection())\r
+ {\r
+ clients.add(client);\r
+ System.out.println("List now contains " + clients.size() + " client(s)");\r
+ return true;\r
+ }\r
+ \r
+ return false;\r
+ }\r
+ \r
+ public void sendMessage(String str)\r
+ {\r
+ forwardMessage(null, str);\r
+ }\r
+ \r
+ // Forwards (or sends) a message\r
+ // When the server receives a message, it will be resent to all clients,\r
+ // but *not* to the client that sent it out in the first place!\r
+ private void forwardMessage(PickEndPoint origin, String str)\r
+ {\r
+ ListIterator itor = clients.listIterator();\r
+ while (itor.hasNext())\r
+ {\r
+ PickEndPoint client = (PickEndPoint) itor.next();\r
+ \r
+ if (client != origin)\r
+ client.send(str);\r
+ }\r
+ }\r
+ \r
+ // Called by the endpoint code when a message is received\r
+ // The manager has to:\r
+ // a) hand message to VAMSAS app\r
+ // b) forward it to other clients if we're the server\r
+ void handleMessage(PickEndPoint origin, String str)\r
+ {\r
+ if (server.isServer())\r
+ forwardMessage(origin, str);\r
+ \r
+ // TODO: pass message to VAMSAS API\r
+ }\r
+ \r
+ void removeEndPoint(PickEndPoint client)\r
+ {\r
+ clients.remove(client);\r
+ System.out.println("List now contains " + clients.size() + " client(s)");\r
+ \r
+ // If there's no endpoints left, then we've lost all connections and\r
+ // need to reinitialize\r
+ if (clients.size() == 0)\r
+ new InitializeThread().start();\r
+ }\r
+ \r
+ private class InitializeThread extends Thread\r
+ {\r
+ public void run()\r
+ {\r
+ System.out.println("Initializing connection...");\r
+ boolean connected = false;\r
+ \r
+ // Loop until we can get a connection (one way or the other)\r
+ while (!connected)\r
+ {\r
+ // Sleep for a rnd time so we don't end up with all the VAMSAS\r
+ // apps trying to initialize servers at the same time\r
+ try { Thread.sleep((int)Math.random()); }\r
+ catch (InterruptedException e) {}\r
+ \r
+ // Attempt to open the server port...\r
+ if (server.isServer() || server.createServer())\r
+ connected = true;\r
+\r
+ // If it fails, then attempt to make a client connection...\r
+ else if (addClientConnection(null))\r
+ connected = true;\r
+ }\r
+ }\r
}\r
}
\ No newline at end of file
static final int PORT = 53782;\r
\r
private ServerSocket serverSocket;\r
+ private boolean isServer = false;\r
\r
- PickServer()\r
+ private PickManager manager;\r
+ \r
+ PickServer(PickManager manager)\r
{\r
+ this.manager = manager;\r
}\r
\r
+ boolean isServer()\r
+ { return isServer; }\r
+ \r
boolean createServer()\r
{\r
try\r
serverSocket = new ServerSocket(PORT);\r
start(); \r
\r
- return true;\r
+ return isServer = true;\r
}\r
catch (IOException e)\r
{\r
// If we fail, just assume another app already has the port\r
- System.out.println(e);\r
+ System.out.println("SERVER: " + e);\r
return false;\r
}\r
}\r
\r
public void run()\r
{\r
- System.out.println("SERVER: listening...");\r
+ System.out.println("SERVER: listening on " + PORT + " - SERVER");\r
\r
// Loop forever, accepting connectons from other clients\r
while (true)\r
{\r
try\r
{\r
- Socket socket = serverSocket.accept();\r
+ Socket socket = serverSocket.accept(); \r
+ System.out.println("SERVER: connection detected");\r
\r
- System.out.println("SERVER: connection made, spawning pipe...");\r
-\r
- // Do something with the socket...\r
- new PickEndPoint(socket);\r
+ manager.addClientConnection(socket);\r
}\r
catch (IOException e) {}\r
}\r
{\r
TestApp app = new TestApp();\r
\r
- PickServer server = new PickServer();\r
+ PickManager manager = new PickManager();\r
\r
- \r
- if (server.createServer() == false)\r
- {\r
- PickEndPoint client = new PickEndPoint();\r
+ // Send 5 test messages...\r
+// for (int i = 0; i < 5; i++)\r
+ while (true)\r
+ { \r
+ try { Thread.sleep((int) (Math.random()*20000)); }\r
+ catch (InterruptedException e) {}\r
\r
- for (int i = 0; i < 10; i++)\r
- client.send();\r
-// client.send();\r
+ int rnd = (int) (Math.random()*100);\r
+ manager.sendMessage("" + rnd);\r
}\r
}\r
\r