【问题标题】:How to stop program running infinite loop on close GUI如何在关闭 GUI 时停止程序运行无限循环
【发布时间】:2012-12-02 08:26:46
【问题描述】:

我有一个使用套接字进行服务器/客户端通信的简单程序。 服务器类包含run()方法,该方法有无限循环等待socket接受。

无论如何,我在构造函数中编写了一个代码来终止处理,

 this.addWindowListener(new java.awt.event.WindowAdapter() {
    @Override
    public void windowClosing(java.awt.event.WindowEvent windowEvent) {
        System.out.println("Close operation server done");
        toClient.println("Bye");
        closeStreams();
        socket = null;
        serverSocket = null;
        System.exit(0);
    }
});

当我阅读 method windowClosing(WindowEvent e) 的 API 时,它说:

当窗口正在关闭时调用。关闭 此时可以覆盖操作。

它表示窗口正在关闭。但是 run() 方法内部的循环仍然获得控制权,并且由于程序的逻辑而不会结束,因此不会关闭窗口(实际上是关闭 GUI),但处理仍在幕后进行。

如何正确强制程序运行?

整个工作服务器类:

import java.awt.*;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.KeyAdapter;
import java.awt.event.KeyEvent;
import java.io.*;
import java.net.*;
import java.util.logging.Level;
import java.util.logging.Logger;
import javax.swing.*;


public class ChatServer extends JFrame
{

    private InetAddress serverAddress;
    private Socket socket;
    private ServerSocket serverSocket;
    private InputStream is;
    private OutputStream os;
    private BufferedReader fromClient;
    private PrintWriter toClient;
    private JButton send;
    private JPanel uperPanel;
    private JPanel midPanel;
    private JPanel downPanel;
    private JTextArea textToSend;
    private JTextArea textToReceive;
    private JLabel addressL;
    private final int port = 5555;
    private boolean idle = false;
    private int timeout = 3000;
    public static String newline = System.getProperty("line.separator");

    private ChatServer()
    {
        this.setGUI();
        this.setVisible(true);
        try
        {
            serverSocket = new ServerSocket(port);
            this.run();
        } catch (IOException ex)
        {
            Logger.getLogger(ChatServer.class.getName()).log(Level.SEVERE, null, ex);
        }

        this.addWindowListener(new java.awt.event.WindowAdapter()
        {
            @Override
            public void windowClosing(java.awt.event.WindowEvent windowEvent)
            {
                idle = true;
                closeStreams();
                socket = null;
                serverSocket = null;
                System.exit(0);
            }
        });
    }

    public void run() throws IOException
    {
        try
        {
            while (true)
            {
                System.out.println("System is running");
                socket = serverSocket.accept();
                System.out.println("Client accepted on server side");
                openStreams();
                toClient.println("Hello: server is connected " + serverAddress.getLocalHost().toString());
                processClient();
                //   closeStreams();
            }
        } catch (java.net.SocketTimeoutException ee)
        {

            closeStreams();
            System.out.println(ee);


        } catch (Exception e)
        {
            System.out.println("Error accepting server " + e);
        }

    }

    public void processClient() throws IOException
    {
        System.out.println("Porcessing start");
        String line = fromClient.readLine();
        try
        {
            while (!(line.equals("Bye")))
            {
                textToReceive.append("He: " + line + newline);
                line = fromClient.readLine();
            }
            closeStreams();

        } catch (IOException ex)
        {

            System.out.println("Error reading from client " + ex);

        }
    }

    private void setGUI()
    {

        this.setSize(375, 314);


        send = new JButton("send");

        try
        {
            addressL = new JLabel("My Server address: " + serverAddress.getLocalHost().toString()
                    + "  Port: " + this.port);
        } catch (Exception e)
        {
            System.out.println("Unknown Host problem " + e);
        }

        textToReceive = new JTextArea(12, 30);
        textToReceive.setLineWrap(true);
        JScrollPane recievedScrolledText = new JScrollPane(textToReceive);
        recievedScrolledText.setVerticalScrollBarPolicy(JScrollPane.VERTICAL_SCROLLBAR_ALWAYS);
        textToReceive.setEditable(false);


        textToSend = new JTextArea(3, 25);
        textToSend.setLineWrap(true);
        JScrollPane sentScrolledText = new JScrollPane(textToSend);
        sentScrolledText.setVerticalScrollBarPolicy(JScrollPane.VERTICAL_SCROLLBAR_ALWAYS);
        textToSend.setEditable(true);

        uperPanel = new JPanel();
        midPanel = new JPanel();
        downPanel = new JPanel();

        uperPanel.add(addressL);


        midPanel.add(recievedScrolledText);
        downPanel.add(sentScrolledText);
        downPanel.add(send);

        Container c = getContentPane();
        c.setLayout(new BorderLayout());
        c.add(uperPanel, "North");
        c.add(midPanel, "Center");
        c.add(downPanel, "South");

        send.addActionListener(new ButtonWatch());
        textToSend.addKeyListener(new KeyWatch());
    }

    private void openStreams() throws IOException
    {

        is = socket.getInputStream();
        fromClient = new BufferedReader(new InputStreamReader(is));
        os = socket.getOutputStream();
        toClient = new PrintWriter(os, true);
        System.out.println("open stream is open on server");
    }

    private void closeStreams()
    {
        try
        {

            if ((toClient != null) && (os != null)
                    && (fromClient != null) && (is != null)
                    && (fromClient != null) && (socket != null))
            {
                toClient.close();
                os.close();
                fromClient.close();
                is.close();
                socket.close();
            }


        } catch (IOException ex)
        {
            System.out.println("Problem closing streams " + ex);
        }
    }

    private class KeyWatch extends KeyAdapter
    {

        public void keyPressed(KeyEvent e)
        {
            if (e.getKeyCode() == KeyEvent.VK_ENTER)
            {
                String line = textToSend.getText();
                textToSend.setText("");
                toClient.println(line);
                textToReceive.append("You: " + line + newline);
            }
        }

        public void keyReleased(KeyEvent e)
        {
            if (e.getKeyCode() == KeyEvent.VK_ENTER)
            {
            }
        }

        public void keyTyped(KeyEvent e)
        {
            if (e.getKeyCode() == KeyEvent.VK_ENTER)
            {
            }
        }
    }

    private class ButtonWatch implements ActionListener
    {

        @Override
        public void actionPerformed(ActionEvent e)
        {
            Object buttonPressed = e.getSource();

            if (buttonPressed == send)
            {
                String line = textToSend.getText();
                textToSend.setText("");
                toClient.println(line);
                textToReceive.append("You: " + line + newline);

                System.out.println("send to client " + line);
            }

        }
    }

    public static void main(String[] args)
    {
        ChatServer s = new ChatServer();
        s.setVisible(true);
    }
}

现在如何在单击 (x) 关闭图标后正确终止它。

【问题讨论】:

  • 对不起。我重复了我的问题,因为前一个问题不清楚/具体,所以答案不属于我的问题。我标记了我之前的问题并要求删除。
  • 只贴相关代码,你真指望我会读完这些?
  • while (true) 没有休息或条件无价!
  • 你看过 setDefaultCloseOperation 和 CloseListener](tips4java.wordpress.com/2009/05/01/closing-an-application) 窗口事件处理程序吗?
  • 我没想到@mouseevent。它没有错误,我只想关闭窗口并让事情终止。 run() 方法获得控制权并且不会释放,所以如何中断它并关闭它。

标签: java sockets terminate


【解决方案1】:

还有:

您看过setDefaultCloseOperationCloseListener 窗口事件处理程序吗?

【讨论】:

    【解决方案2】:

    使用Thread 并将其设置为daemon 线程。在这里,我更改了代码的前几行:

    public class ChatServer extends JFrame implements Runnable
    {
        private ChatServer()
        {
            this.setGUI();
            this.setVisible(true);
            try
            {
                serverSocket = new ServerSocket(port);
                Thread accept = new Thread(this);
                accept.setDaemon(true);
                accept.start();
            } catch (IOException ex)
            {
                Logger.getLogger(ChatServer.class.getName()).log(Level.SEVERE, null, ex);
            }
    

    【讨论】:

    • 未使用线程,我想中断run() 方法并启用关闭
    • @SalehFeek 嗯,这是main 线程,在这里使用,请参阅编辑。
    • 非常感谢,我整天都在努力解决它。你的解决方案是完美的。谢谢。
    • ,上一个答案(编辑前)是我的代码的工作答案。我尝试了代码(编辑后)它不起作用,它给出了一个异常。 Exception in thread "main" java.lang.IllegalThreadStateException 我正在使用编辑前的代码。无论如何谢谢你
    【解决方案3】:

    windowClosing 处理程序中关闭您的服务器套接字serverSocket.close()。这将在您的接受循环中抛出SocketException 并中断它。您可以捕获它并进行处理以进行正常关机。

    【讨论】:

      猜你喜欢
      • 2015-02-07
      • 2018-11-19
      • 2021-07-28
      • 1970-01-01
      • 2023-02-26
      • 1970-01-01
      • 1970-01-01
      • 2023-01-13
      • 1970-01-01
      相关资源
      最近更新 更多