通过消息Java关闭多线程套接字服务器

问题描述 投票:0回答:1

我有一个多线程进程,它侦听消息并对其进行处理。如果收到的消息之一是“ shutdown”,我希望能够关闭该进程。除了关机部分,我已经实现了所有功能。

我有一个用java.net.ServerSocket方法扩展start的“多”类。里面...

java.net.Socket socket = null;
while (true) {
            try {
                socket = this.accept();
                new Thread(new SocketThread(socket, verifier, threading)).start();

            } catch (IOException e) {
                e.printStackTrace();
            }
        }

那个SocketThread是implements Runnable的另一个类。有什么办法可以使这项工作完成?

java multithreading maven sockets runnable
1个回答
0
投票

我以前不必这样做(因为我通常不会发现自己必须写大量的原始SocketServer),但是使用这种类型的线程协调,我会尝试执行以下操作……

public class App {
    public static void main(String[] args) {
        new App().run();
    }

    public void run() {
        try {
            System.out.println("Starting...");
            AtomicBoolean running = new AtomicBoolean(true);
            try (ServerSocket socketServer = new ServerSocket(10101)) {
                while (running.get()) {
                    System.out.println("Started.");
                    Socket socket = socketServer.accept();
                    System.out.println("Connection accepted.");
                    if (running.get()) {
                        Thread thread = new Thread(new SocketHandler(socket, running));
                        thread.start();
                    } else {
                        System.out.println("Stopping...");
                    }
                }
            }
            System.out.println("Stopped.");
        } catch (IOException e) {
            e.printStackTrace();
        }
    }

    static class SocketHandler implements Runnable {
        private final Socket socket;
        private final AtomicBoolean running;

        SocketHandler(Socket socket, AtomicBoolean running) {
            this.socket = socket;
            this.running = running;
        }

        @Override
        public void run() {
            try {
                System.out.println("Client connected.");
                try (BufferedReader in = new BufferedReader(new InputStreamReader(socket.getInputStream()))) {
                    String command = in.readLine();
                    while (command != null && !command.equals("shutdown")){
                        // process command
                        System.out.println("Command: " + command);
                        command = in.readLine();
                    }
                    if (!"shutdown".equals(command)) {
                        System.out.println("Shutdown command received");
                        running.set(false);
                        try (Socket tmpSocket = new Socket("localhost", 10101)) {}
                    }
                }
                System.out.println("Client disconnected.");
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
    }
}

Updated:处理客户端断开连接的示例代码。感谢@ user207421突出显示此内容(谢谢)。

我不太确定Java Socket API的可中断性,但为此我投入了一些代码,就好像您在等待accept()一样,那么只会在下一个连接上检查运行标志(您可能需要考虑使用interrupt()的替代方法)。希望对您有所帮助。

更新:更改了示例,以建立与服务器的连接以使其解除阻止。

注意:请确保在退出前清理Socket资源。我没有包括使代码尽可能简短。

更新:您可能还会发现此测试有用:

public class RawSocketServerTest {
    @Test
    public void should_shutdown_when_sent_shutdown_command() throws IOException, InterruptedException {
        // given
        Thread thread = new Thread(() -> { new App().run(); });
        thread.start();
        sleep(1000);    // waiting for App to start; replace with something more robust (e.g. awaitility)
        Socket socket = new Socket("localhost", 10101);
        BufferedWriter out = new BufferedWriter(new OutputStreamWriter(socket.getOutputStream()));

        // when
        out.write("shutdown");
        out.newLine();
        out.flush();

        // then
        thread.join();  // App exited normally
    }
}
© www.soinside.com 2019 - 2024. All rights reserved.