2

StackOverflow 上的第一个问题,如果我问错了,请见谅。

基本上,我正在编写一个多播客户端,它无限期地监听多播地址,直到用户在控制台中键入“退出”。我发现为 MulticastSocket 设置 SO_TIMEOUT,检查是否已键入“退出”,然后返回接收方法调用并没有真正起作用,因为可以在超时后立即发送数据包并检查控制台块. 所以我相信最好的选择是简单地让2个线程去一个监听套接字并阻塞直到它收到一些东西,另一个线程监听控制台直到被告知退出。我唯一的问题是我不确定如何让控制台监听线程告诉套接字线程关闭套接字并终止。System.end() 会起作用,但我担心我会打开一个套接字,等等。

TLDR;有没有办法让类的 main 方法启动一个线程,然后在该线程结束后以特定的方式响应?我需要在一个线程上收听控制台,在另一个线程上收听 MulticastSocket,或者只是在客户端类的主线程中收听。

感谢大家。

4

1 回答 1

1

我会打电话Socket.close()关闭套接字。这将在该线程中产生 IOException。所以在这样做之前,我会设置一个标志closed = true;,让另一个线程在打印错误之前检查这个,即如果你已经关闭,则不要打印 IOException。像这样的东西。

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();
    }
}

例如,在你的主线程中你可以做

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.
于 2016-04-20T05:47:22.470 回答