0

I am creating a client/server program with sockets. Each time a new client connects it creates a new instance of the newClient class which handles the connection and creates a new PrintStream for that client. I then want to output the same data to each of the PrintStreams for the clients. How do I do this?

    public void startServer(){
    Thread serverstart = new Thread(){
        public void run() {
                try {       
                    serversocket = new ServerSocket(socket);

                    while(true){
                        Socket skt = serversocket.accept();
                        new Thread(new newClient(skt)).start();
                    }
            } catch (IOException e){
                e.printStackTrace();
              }
        }
    };serverstart.start();
}
class newClient implements Runnable {
    private Socket socket;
    public newClient(Socket skt){
        this.socket = skt;
    }
    @Override
    public void run(){
        try {
        PrintStream output = new PrintStream(socket.getOutputStream());
        } catch(IOException ioe){
            ioe.printStackTrace();
        }
    }
}

Here is the method that sends the data:

        public void sendData(){         
                if(preview == 1)
                    tallydata = "1";
                else if(preview == 2)
                    tallydata = "2";
                else if(preview == 3)
                    tallydata = "3";
                else if(preview == 4)
                    tallydata = "4";
                else if(preview == 5)
                    tallydata = "5";
                else if(preview == 6)
                    tallydata = "6";

                if(program == 1)
                    tallydata = tallydata + " 1";
                if(program == 2)
                    tallydata = tallydata + " 2";
                if(program == 3)
                    tallydata = tallydata + " 3";
                if(program == 4)
                    tallydata = tallydata + " 4";
                if(program == 5)
                    tallydata = tallydata + " 5";
                if(program == 6)
                    tallydata = tallydata + " 6";

                output.print(tallydata);
        try{
                serversocket.close();
                socketname.close();
            } catch(IOException e){
                e.printStackTrace();
            } 

Thanks in advance!

Alex A
  • 23
  • 8
  • Sidenote: Replace the if-statements in sendData by 'String tallydata = Integer.toString(preview) + Integer.toString(program); – isnot2bad Nov 22 '13 at 00:50

1 Answers1

0

At first blush, it seems like you would register each 'newClient' as a listener - maintain a list of them, and when you want to send output, iterate through and send the output to each registered listener. This sort of multiplexing (muxing) is reminiscent of the *nix 'T' stream concept.

Some details that you'll want to consider:

  1. Use weak references so you don't have a memory leak ( ArrayList<WeakReference<Runnable>> - How to tidy up best? has a nice WeakRunnableList implementation that is probably quite close to what you are looking for)

  2. This logic could be consolidated into a MuxingWriter implementation of some sort that allows you to register multiple targets. The end result would be a pretty nice reusable component - nice and encapsulated. Still use weak references, though.

EDIT: example of MuxingWriter implementation:

public class MuxingWriter extends Writer{
private final List<WeakReference<Writer>> registeredWriters = new CopyOnWriteArrayList<WeakReference<Writer>>(); // thread safety

public void registerWriter(Writer writer){ 
  registeredWriters.add(new WeakReference(writer);
}
write(char[] str, int off, int len){
  Iterator<WeakReference<Writer>> it = registeredListeners.iterator();
  while(it.hasNext()){
     Writer writer = it.next();
     if (ww == null){
       it.remove(); // clean up dead references
     } else {
        ww.write(str, off, len);
     }

  }
}
flush(){
// do similar stuff do write(), but call ww.flush()
}
close(){
// do similar stuff do write(), but call ww.close()
}

The above should give you an idea on the approach (I haven't tested the above, just writing it off the cuff).

To use this, put the MuxingWriter into the server. Then make your NewClient class register it's output with the MuxingWriter.

Community
  • 1
  • 1
Kevin Day
  • 16,067
  • 8
  • 44
  • 68
  • Ok thanks, although I am not really sure how to do that. How do I register the newClients as listeners? – Alex A Nov 22 '13 at 05:35
  • with a method called addListener(Writer writer) - when called, it adds the new writer to the list. When your MuxingWriter receives a write() call, you loop through the registered listeners, dereference the weak reference (and remove the weak reference if it's no longer valid), then call the same write() method on the listener. – Kevin Day Nov 22 '13 at 17:31
  • ok - just added some sample code to give you a feel for how to do this. – Kevin Day Nov 22 '13 at 17:42