2012-08-04 30 views
0

下面的代碼是我用來創建一個端口掃描器,但是,當我點擊「掃描」它執行但gui凍結,直到它完成掃描,是否有任何可能的方式來允許掃描時執行其他操作?我創建了一個使用java的portscanner,但是當我點擊執行它只是凍結

import javax.swing.*; 
import java.awt.*; 
import java.awt.event.ActionEvent; 
import java.awt.event.ActionListener; 
import java.net.InetAddress; 
import java.net.Socket; 
import java.net.UnknownHostException; 

public class PortScannerGUI extends JFrame implements ActionListener 
{ 
JPanel Panel = new JPanel(null); 
JTextField Field = new JTextField(); 
JButton Button = new JButton(); 
JTextArea Area = new JTextArea(); 
JButton limit = new JButton("limit"); 

public PortScannerGUI() 
{ 
    super(); 
    setSize(350, 400); 
    setDefaultCloseOperation(EXIT_ON_CLOSE); 
    setResizable(false); 
    setLocationRelativeTo(null); 
    LoadUI(); 
} 

public void LoadUI() 
{ 
    Area.setBounds(20, 50, 310, 310); 
    Area.setBorder(BorderFactory.createLineBorder(Color.BLUE)); 
    Area.setEditable(false); 

    Field.setBounds(20, 10, 200, 35); 

    Button.setBounds(230, 10,100, 35); 
    Button.setText("Scan"); 
    Button.addActionListener(this); 

    Panel.add(Field); 
    Panel.add(Area); 
    Panel.add(Button); 
    add(Panel); 
    setVisible(true); 
} 

public static void main(String[] args) 
{ 
    PortScannerGUI Main = new PortScannerGUI(); 
} 

@Override 
public void actionPerformed(ActionEvent arg0) 
{ 
    Thread Runner = new Thread(); 
    Runner.start(); 
    int j=0; 
    String str = Field.getText(); 
    for(int i=1;i<str.length();i++) 
    { 
     if(str.substring(i-1, i).equals(".")) 
     { 
      j++; 
     } 
    } 
    if(!str.equals("") || j==4 || j==6) 
    { 
     try 
     { 
      InetAddress IP = InetAddress.getByName(str); 
      PortScanner P = new PortScanner(IP); 
     } 
     catch (Exception e){} 
    } 
    else 
    { 
     JOptionPane.showMessageDialog(null, "Not an IP address"); 
    } 

} 
} 

該頂部代碼是用於GUI部分的代碼和下面是實際掃描端口的代碼..

import java.io.IOException; 

import java.net.InetAddress; 

import java.net.Socket; 

public class PortScanner 
{ 
public PortScanner(InetAddress iA) 
{ 
    for (int port = 1; port <= 65535; port++) 
    { 
     try 
     { 
      Socket s = new Socket(iA, port); 
      System.out.println("Port " + port + " is open"); 
      s.close(); 
     } 
     catch(IOException e) 
     { 

     } 
    } 
} 
} 

回答

5

這是在做長時間運行的過程的一個典型的例子Swing事件線程(EDT或Event Dispatch Thread),從而凍結該線程,從而導致GUI不起作用。我們一次又一次地看到這類事情,解決方案是相同的,並且相對簡單:在後臺線程中執行長時間運行的進程,例如可以由SwingWorker提供的進程。欲瞭解更多信息,請閱讀Concurrency in Swing,或在本網站上搜索類似的問題,因爲再次討論了很多。

關於你的代碼還有一點,從未做到這一點:

catch(IOException e) 
    { 

    } 

如果忽略異常,你從字面上盲目飛行。最起碼,打印堆棧跟蹤,即,:

catch(IOException e) 
    { 
     e.printStackTrace(); 
    } 

同樣在這裏:

 try { 
     InetAddress IP = InetAddress.getByName(str); 
     PortScanner P = new PortScanner(IP); 
    } catch (Exception e) { 
     e.printStackTrace(); // **** add this! 
    } 

我自己,我會建立在端口掃描工具構造的端口掃描工具的對象,而是將運行用一種單獨的公共方法掃描,稱爲scan()。這將允許我在事件線程上設置PortScanner對象,然後通過調用其scan()方法在後臺線程中對其進行掃描。有時候這更方便。

編輯
我也想給的端口掃描工具類有一個PropertyChangeListener添加到它的能力,因此,它可以允許其他類聽其是否有變化,包括對端口的信息。這樣您就可以在GUI中發佈PortScanner端口信息。最簡單的方法是讓SwingWorker對象擴展SwingWorker,因爲SwingWorkers內置了PropertyChangeSupport。然後,您可以使用發佈/處理方法對將發佈的端口信息發佈到GUI,而不是在println語句中打印出來。我已經鏈接到上面的教程描述瞭如何做到這一點,如果您遇到困難,我們可以幫助您解決詳細問題。

+0

我必須對我的代碼做些什麼改動? – user1576203 2012-08-04 14:57:59

+0

@ user1576203:請參閱編輯。至於「更改」,我們通常不會爲您編寫代碼更改,而是幫助您解決特定問題。您應該首先閱讀並理解本教程,因爲它會引導您進行必要的操作。然後繼續嘗試創建自己的SwingWorker,並且如果您在堆棧溢出問題上發佈另一個問題。 – 2012-08-04 15:00:46

相關問題