2012-11-30 57 views
0

我有一個使用套接字的服務器/客戶端通信的簡單程序。 服務器類包含run()方法,該方法有無限循環等待套接字接受。如何停止程序在關閉GUI上運行無限循環(java)

任何方式,我在構造函數中對關閉處理做終止寫了一碼,

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

當我讀了methodwindowClosing(WindowEvent e)它說的API:

時調用窗口正在關閉。此時可以覆蓋關閉 操作。

它說一個窗口正在關閉的過程中。但run()方法中的循環仍然獲得控制權,並且由於程序的邏輯而不會完成,因此窗口不會關閉(實際上GUI已關閉),但處理仍在幕後工作。

更新:

run()方法:

public void run() 
{ 
    try 
    { 
     while (true) 
     { 
      idle = 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 (Exception e) 
    { 
     System.out.println("Error accepting server " + e); 
    } 
} 

processClient()方法:

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

如何正確運行執行程序?

更新2:整個工作服務器類:

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.*; 

/** 
* 
* @author S 
*/ 
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); 
    } 
} 

現在如何在交易完成後終止。

+1

演示你的循環。一般來說,正確的方法是持有對運行循環的Thread的引用,並調用Thread.interrupt,其中'run'方法定期檢查'Thread.interrupted()'狀態。 –

+1

infiny循環是在你沒有顯示的代碼行中產生的,我敢打賭代碼行是第57行。或/和第875次,以更好地幫助更快地發佈SSCCE,展示你的問題,簡短,可運行,可編譯,關閉Socket,以及空JFrame,否則這裏的一切都是黑暗的鏡頭, – mKorbel

+0

針對這裏的答案,大多數(通過使用API​​中實現的方法關閉)工作線程和連接,Socker,RMI,眼鏡蛇....是異步的,那麼不能保證依賴於,隱藏JFrame,然後用terminate/close/expire/whatever來實現,但是沒有問題與默認情況下的套接字,OP錯誤不張貼或描述 – mKorbel

回答

1

-那麼它最好使用Executor來跨越線程。

-然後用cancel(true)submit()方法來中斷這個特定的線程。

-如果你想要去Thread直接,那麼你可以使用interrupt()interrupted()方法中斷thread

1

更改您的服務器環路爲而不是無限。

volatile boolean runFlag = true; 
while (runFlag) { 
    //do server stuff 
} 

並得到您的關閉方法來標記服務器停止。

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(); 
    runFlag = false; 
    } 
}); 

您可能希望讓任何東西,正在進行中得到完成,你不進步當前中斷任何主服務器循環後流結束的東西搬到。