如何在关闭的GUI上停止程序运行无限循环

时间:2012-11-30 19:16:28

标签: java sockets terminate

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

无论如何,我在构造函数中编写了一个代码,用于在close,

上进行处理
 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)关闭图标后正确终止它。

3 个答案:

答案 0 :(得分:2)

另外:

您是否查看了setDefaultCloseOperationCloseListener窗口事件处理程序?

答案 1 :(得分:1)

使用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);
        }

答案 2 :(得分:0)

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