2

First question here on StackOverflow, so please excuse me if I ask this incorrectly.

Basically, I'm writing a Multicast Client that indefinitely listens to a multicast address until the user types "quit" into the console. I've found that setting SO_TIMEOUT for the MulticastSocket, checking if "quit" has been typed, and then returning to the receive method call doesn't really work since a packet could be sent right after the timeout and the check of the console blocks. So I believe the best option is to simply have 2 threads going where one listens on the socket and blocks until it receives something, and the other thread listens to the console until told to quit. The only issue I have is that I'm unsure of how to go about having the console listening thread tell the socket thread to close the socket and terminate. System.end() would work but I fear that I'd leave a socket open, etc.

TLDR; Is there a way for the main method of a class to start a thread, and then respond a specific way once that thread ends? I need to listen to the console on one thread and a MulticastSocket on another, or just in the main of the client class.

Thanks everyone.

1 Answers1

1

I would call Socket.close() to close the socket. This will produce an IOException in that thread. so before doing this I would set a flag like closed = true; and have the other thread check this before printing the error i.e. don't print an IOException if you have been closed. Something like this.

public class SocketListener implements Runnable, Closeable {
    final MulticastSocket socket;
    final Consumer<DatagramPacket> packetConsumer;
    volatile boolean closed;

    public SocketListener(MulticastSocket socket, Consumer<DatagramPacket> packetConsumer) {
        this.socket = socket;
        this.packetConsumer = packetConsumer;
    }

    @Override
    public void run() {
        DatagramPacket packet = new DatagramPacket(new byte[1024], 1024);
        try {
            while(!closed) {
                socket.receive(packet);
                packetConsumer.accept(packet);
            }
        } catch (IOException e) {
            if (!closed)
                e.printStackTrace();
        }
    }

    @Override
    public void close() throws IOException {
        closed = true;
        socket.close();
    }
}

for example, in your main thread you can do

MulticastSocket socket = ...
Consumer<DatagramPacket> packetConsumer = ...
try (SocketListener listener = new SocketListener(socket, packetConsumer)) {
    boolean finished = false;
    do {
        // read from the console
        if (some condition)
            finished = true;
    } while(!finished);
} // calls close() for you.
Peter Lawrey
  • 525,659
  • 79
  • 751
  • 1,130
  • A little confused here. How would the thread that reads from the console interact with the socket listener's close? I think for my own code, I'd have my Client implement the Runnable interface, but I'm just a little unsure of how you intend to have the two threads interact. I haven't done much with threading so apologies if my questions seem mundane. – ruhrohraggy Apr 20 '16 at 18:38
  • @user16728 You have have the console reading thread call the `close()` method. – Peter Lawrey Apr 20 '16 at 18:41
  • @user16728 I have added an example to my answer. – Peter Lawrey Apr 20 '16 at 18:45