簡體   English   中英

多線程套接字服務器通過消息 Java 關閉

[英]Multi thread socket server shutdown by message Java

我有一個多線程進程來監聽消息並處理它們。 如果收到的消息之一是“關閉”,我希望能夠關閉該過程。 除了關閉部分,我已經實現了所有內容。

我有一個“Multi”類,它使用start方法擴展java.net.ServerSocket 里面...

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類。 有什么辦法可以使這項工作?

我以前不必這樣做(因為我通常不會發現自己必須編寫很多原始 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);
            Collection<Socket> sockets = new ArrayList<>();
            Collection<Thread> threads = new ArrayList<>();
            try (ServerSocket socketServer = new ServerSocket(10101)) {
                System.out.println("Started.");
                while (running.get()) {
                    Socket socket = socketServer.accept();
                    sockets.add(socket);
                    if (running.get()) {
                        Thread thread = new Thread(new SocketHandler(socket, running));
                        thread.start();
                        threads.add(thread);
                    }
                }
                System.out.println("Stopping...");
                sockets.forEach(socket -> {
                    try {
                        socket.close();
                    } catch (IOException e) {
                        e.printStackTrace();
                    }
                });
                threads.forEach(thread -> {
                    try {
                        thread.join();
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }
                });
            }
            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()))) {
                    boolean connected = true;
                    while (connected){
                        String command = in.readLine();
                        System.out.println("Command received: " + command);
                        if (command == null) {
                            connected = false;
                        } else if (command.equals("shutdown")) {
                            running.set(false);
                            try (Socket tmpSocket = new Socket("localhost", 10101)) {}
                        }
                        // process other commands
                    }
                }
                System.out.println("Client disconnected.");
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
    }
}

更新:更改示例以建立與服務器的連接以使其解除阻塞。

更新:處理客戶端斷開連接情況的示例代碼。 感謝@user207421 突出顯示這一點(謝謝)。

更新:更改了示例代碼以處理多個客戶端套接字/線程。 請注意,當您關閉當前剛剛打印到 stderr 的套接字時,它將通過異常。 您可能希望以不同的方式處理。

更新:您可能還會發現模擬多個客戶端連接的代碼很有幫助:

public class Clients {
    public static void main(String[] args) {
        Thread thread1 = new Thread(() -> new NormalClient().run());
        Thread thread2 = new Thread(() -> new NormalClient().run());
        Thread thread3 = new Thread(() -> new NormalClient().run());
        Thread thread4 = new Thread(() -> new NormalClient().run());
        Thread thread5 = new Thread(() -> new ShutdownClient().run());
        thread1.start();
        thread2.start();
        thread3.start();
        thread4.start();
        thread5.start();
    }
}

class NormalClient {
    void run() {
        try {
            try (Socket socket = new Socket("localhost", 10101);
                 BufferedWriter out = new BufferedWriter(new OutputStreamWriter(socket.getOutputStream()))) {

                for (int i = 0; i < 10; i++) {
                    out.write("hello " + i);
                    out.newLine();
                    out.flush();
                    sleep(1000);
                }
            }
        } catch (IOException | InterruptedException e) {
            e.printStackTrace();
        }
    }
}

class ShutdownClient {
    void run() {
        try {
            try (Socket socket = new Socket("localhost", 10101);
                 BufferedWriter out = new BufferedWriter(new OutputStreamWriter(socket.getOutputStream()))) {

                sleep(8000);
                out.write("shutdown");
                out.newLine();
                out.flush();
            }
        } catch (IOException | InterruptedException e) {
            e.printStackTrace();
        }
    }
}

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM