Fixed up code, made it prettier, it now follows the stylguide better and is more readable.
git-svn-id: https://robotics.mvla.net/svn/frc971/2013/trunk/src@4182 f308d9b7-e957-4cde-b6ac-9a88185e7312
diff --git a/971cv/src/org/spartanrobotics/AccepterThread.java b/971cv/src/org/spartanrobotics/AccepterThread.java
new file mode 100644
index 0000000..ad599de
--- /dev/null
+++ b/971cv/src/org/spartanrobotics/AccepterThread.java
@@ -0,0 +1,140 @@
+/**
+ *
+ */
+package org.spartanrobotics;
+
+/**
+ * @author daniel
+ * Accepts clients for data server
+ */
+
+import java.io.IOException;
+
+import java.nio.ByteBuffer;
+import java.nio.channels.ServerSocketChannel;
+import java.nio.channels.SocketChannel;
+
+import java.util.ArrayList;
+import java.util.List;
+import java.util.Map;
+import java.util.logging.Logger;
+
+/** Thread accepts new connections for the server and sends data to them
+ * without blocking.
+ */
+public class AccepterThread implements Runnable {
+
+ private final static Logger LOG = Logger.getLogger(
+ AccepterThread.class.getName());
+
+ private ServerSocketChannel sock;
+
+ private List<Client> connected = new ArrayList<Client>();
+
+ private Thread t;
+
+ /** Constructor
+ *
+ * @param sock is the ServerSocketChannel that you want to monitor
+ */
+ public AccepterThread(ServerSocketChannel sock) {
+ t = new Thread(this, "Accepter Thread");
+ t.setPriority(Thread.NORM_PRIORITY - 1);
+ //lowish priority so Image Processor overrides it
+ this.sock = sock;
+ t.start();
+ }
+
+ /** Runs in separate thread. Continually accepts new connections. */
+ public void run() {
+ SocketChannel clientSock;
+ while (true) {
+ try {
+ clientSock = sock.accept();
+ //our writes must not block
+ clientSock.configureBlocking(false);
+ Client client = new Client();
+ client.channel = clientSock;
+ connected.add(client);
+ }
+ catch (IOException e) {
+ LOG.warning("Cannot serve image processing results to client:"
+ + e.getMessage());
+ Messages.warning("Cannot serve image processing results to client:"
+ + e.getMessage());
+ }
+ }
+ }
+
+ /** Sends a message to all currently connected clients.
+ *
+ * @param message is the message that you want to send.
+ */
+ public void sendtoAll(ByteBuffer message) {
+ /* Copy our connected list, so we don't have
+ * to hold our lock forever if the writes block.
+ */
+ List<Client> connectedTemp = new ArrayList<Client>();
+ for (Client client : connected) {
+ connectedTemp.add(client);
+ }
+
+ int result;
+ for (Client client : connectedTemp) {
+ try {
+
+ /** If this socket has data from the
+ * last send operation still waiting to be
+ * sent, send this instead of our original
+ * message. Since we generally want only
+ * current data, our original message will
+ * not be missed. However, it is imperative
+ * that we finish our pending transmission,
+ * because an incomplete transmission could
+ * leave a client thread somewhere blocking
+ * indefinitely.
+ */
+ if (client.toSend != null) {
+ message = client.toSend;
+ }
+
+ result = client.channel.write(message);
+
+ /*if our send buffer is full, store our message away
+ * so we can try again later without halting the thread.
+ */
+ if (message.remaining() > 0) {
+ client.toSend = message;
+ //check and update our count of failed send attempts
+ ++client.failedAttempts;
+ if (client.failedAttempts >= 100) {
+ //Socket has become dysfunctional
+ LOG.info("Write would have blocked 100 times. Assuming peer disconect.");
+ connected.remove(client);
+ }
+ }
+
+ if (result == -1) {
+ //The write failed. This is probably because the client disconnected.
+ LOG.info("Write returned -1. Client has probably disconnected.");
+ connected.remove(client);
+ }
+ }
+ catch (IOException e) {
+ //The write failed. This is probably because the client disconnected.
+ LOG.info("Write threw IOException. Client has probably disconnected.");
+ connected.remove(client);
+ }
+ }
+ }
+
+ /** Overloaded sendtoAll method for byte arrays. */
+ public void sendtoAll(byte[] message) {
+ sendtoAll(ByteBuffer.wrap(message));
+ }
+
+ /** Overloaded sendtoAll method for Strings. */
+ public void sendtoAll(String message) {
+ sendtoAll(message.getBytes());
+ }
+}