// // SocketDataServer.java // /* VisAD system for interactive analysis and visualization of numerical data. Copyright (C) 1996 - 2017 Bill Hibbard, Curtis Rueden, Tom Rink, Dave Glowacki, Steve Emmerson, Tom Whittaker, Don Murray, and Tommy Jasmin. This library is free software; you can redistribute it and/or modify it under the terms of the GNU Library General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This library is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Library General Public License for more details. You should have received a copy of the GNU Library General Public License along with this library; if not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA */ package visad.data; import java.io.*; import java.net.*; import java.rmi.RemoteException; import java.util.Vector; import visad.*; /** * A class for exporting data to a socket stream. Whenever the given * DataReference's data changes, it is sent across the socket to any clients * that are listening. */ public class SocketDataServer { /** * The main socket for this SocketDataServer. */ protected ServerSocket socket; /** * List of client sockets listening to this SocketDataServer. */ protected Vector sockets = new Vector(); /** * List of output streams for client sockets. */ protected Vector outs = new Vector(); /** * The socket's port. */ protected int port; /** * DataReference whose data is linked to the socket stream. */ protected DataReferenceImpl ref; /** * Whether the server is still active. */ protected boolean alive = true; /** * Code for monitoring incoming clients. */ private Runnable connect = new Runnable() { public void run() { while (alive) { try { // wait for a new socket to connect Socket s = socket.accept(); if (!alive) break; synchronized (sockets) { if (s != null) { // add client to the list sockets.add(s); // add client's input and output streams to the list ObjectOutputStream out = new ObjectOutputStream(s.getOutputStream()); outs.add(out); // send the current data to the client Data data = SocketDataServer.this.ref.getData(); out.writeObject(data); } } } catch (IOException exc) { } } } }; /** * Cell for monitoring data changes. */ private CellImpl commCell = new CellImpl() { public synchronized void doAction() throws VisADException, RemoteException { // send new data to each client using its socket synchronized (sockets) { Data data = SocketDataServer.this.ref.getData(); int i = 0; while (i < sockets.size()) { Socket s = (Socket) sockets.elementAt(i); ObjectOutputStream out = (ObjectOutputStream) outs.elementAt(i); try { out.writeObject(data); i++; } catch (IOException exc) { // something wrong with this socket; kill it killSocket(i); } } } } }; /** * Construct a SocketDataServer with the given port and data reference. */ public SocketDataServer(int port, DataReferenceImpl ref) throws VisADException, IOException { this.port = port; this.ref = ref; // create a server socket at the given port socket = new ServerSocket(port); // monitor incoming client socket connections Thread connectThread = new Thread(connect); connectThread.start(); // monitor data changes commCell.addReference(ref); } /** * Shut down the given socket, and removes it from the socket vector. */ private void killSocket(int i) { ObjectOutputStream out = (ObjectOutputStream) outs.elementAt(i); Socket s = (Socket) sockets.elementAt(i); // shut down socket output stream try { out.close(); } catch (IOException exc) { } // shut down socket itself try { s.close(); } catch (IOException exc) { } // remove socket from socket vectors sockets.remove(i); outs.remove(i); } /** destroys this server and kills all associated threads */ public void killServer() { // set flag to cause server's threads to stop running alive = false; // shut down all client sockets synchronized (sockets) { while (sockets.size() > 0) killSocket(0); } // shut down server socket try { socket.close(); } catch (IOException exc) { } } }