В следующем коде я пытаюсь запустить и остановить сервер на кнопке с помощью java-апплета. Start хорошо работает с потоком, но я хочу остановить сервер на кнопке. Я использовал переменную volatile , но сервер не останавливается.

Вот код:

public class TCPServer extends Thread {
    public static final int SERVERPORT = 8002;
    private boolean running = false;
    public volatile boolean stop = false;
    public Socket client = null;

    public static void main(String[] args) {
        ServerBoard frame = new ServerBoard();
        frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        frame.pack();
        frame.setVisible(true);
    }

    public void run() {
        super.run();
        running = true;
        try {
            System.out.println("Server Has Started........ \n Waiting for client........");
            ServerSocket serverSocket = new ServerSocket(SERVERPORT);
            try {
                while (!stop && running) {
                    client = serverSocket.accept();
                    System.out.println("Connection Accepted......");
                    BufferedReader in = new BufferedReader(new InputStreamReader(client.getInputStream()));
                    String usercmnd = in.readLine();
                    if (usercmnd != null) {
                        Runtime runtime = Runtime.getRuntime();
                        Process p = runtime.exec(usercmnd);
                    }
                }
                if (stop) {
                    serverSocket.close();
                    client.close();
                    System.out.println("Server Has Stopped");
                    System.exit(0);
                }

            } catch (Exception e) {
                System.out.println("Error");
                e.printStackTrace();
            }
        } catch (Exception e) {
            System.out.println("Error");
            e.printStackTrace();
        }

    }

    public void requestStop() {
        stop = true;
    }
}

Но всякий раз, когда я нажимаю кнопку остановки, которая останавливает сервер, он не показывает никаких выходных данных на консоли, как я ожидал по коду. Он также не показывает никаких ошибок, вот код кнопки остановки

stopServer = new JButton("Stop");
stopServer.addActionListener(new ActionListener() {
    @Override
    public void actionPerformed(ActionEvent e) {
        stopServer.setEnabled(false);
        startServer.setEnabled(true);
        mServer = new TCPServer();
        mServer.requestStop();

    }
});
1
Nilesh Indalkar 5 Сен 2016 в 14:18

5 ответов

Лучший ответ

Это не останавливается, потому что вы создаете новый экземпляр перед его остановкой, и вы даже не запускаете его сначала, пока вы должны вызвать requestStop() в текущем экземпляре TCPServer.

// Here you create a new instance instead of using the existing one
mServer = new TCPServer();
mServer.requestStop();
4
Nicolas Filotto 5 Сен 2016 в 11:35

Из-за https://docs.oracle .com / javase / 7 / docs / api / java / net / ServerSocket.html # accept ().

ServerSocket::accept - это метод блокировки, поэтому переменную stop можно проверить только между успешными соединениями.

Вы можете установить тайм-аут ServerSocket с помощью ServerSocket::setSoTimeout (и catch SocketTimeoutException) или interrupt Server thread and catch InterruptedException.

Оба исключения будут выброшены из ServerSocket::accept.

Обратите внимание, что прерывание потока предпочтительнее тайм-аутов и повторного перехвата исключений.

0
Nikolay 5 Сен 2016 в 11:29

Попробуй это:

public void requestStop() {
    stop = true;
    interrupt();
}

Однако в этом случае мы не можем гарантировать, что уже обрабатывающая логика будет успешно завершена.

Кроме того, вы пытаетесь вызвать requestStop для нового экземпляра TCPServer вместо уже существующего.

0
Eugene Chipachenko 5 Сен 2016 в 11:35

Ваш код client = serverSocket.accept(); блокируется. Итак, как только вы нажали кнопку «stopServer», вы запросили остановку, но она будет выполнена только после того, как клиент отправит следующий запрос на сервер. Что вам нужно сделать, так это запустить вашу логику в вашем методе run () в отдельном потоке и поймать там InterruptedException и ClosedByInterruptException, очистить и вернуться туда. Щелкнув по кнопке stopButton, вы вызовете метод interrupt () в своем потоке. Прочтите об этом здесь

0
Michael Gantman 5 Сен 2016 в 11:37

В вашей реализации ActionListener для кнопки остановки вы получаете доступ к другому экземпляру TCPServer (так как вы создаете новый). Итак, вы устанавливаете значение «Стоп» для второго объекта. Это не влияет на первый экземпляр, созданный с помощью кнопки запуска.

Попробуйте создать экземпляр TCServer вне вашей реализации прослушивателя действий для обеих кнопок и используйте этот единственный экземпляр для обеих.

0
Loic Mouchard 5 Сен 2016 в 11:29