0

I'm working on a Java Network Application in Eclipse, already plenty of detail, and the app functionality is to perform an ip scan of the network and a port scan of a particular ip address. here's the link to github to project https://github.com/zentech/IpScannerX

The problem? ip scan functionality works fine, but I have not been able to solve the port scanning section.

Both the ip scan and port scan class extend the SwingWorker class which you have to implement the doInBackGround() method which in turn create a pool of scannable ip/ports and send the pool into chunks to the callable class.

Then when result.isDone() is true I add data to the Node list which contains objects of type node, every single node has ip, mac, hostname, ports ect... then the process() method is called in which I add data to the JTable and publish to the app.

The ip scanner finishes first, the port scanner runs and I'm logging to the terminal and I can see it is detecting open ports. the problem here's collecting the ports adding to Node list for each host and posting to JTable.

Because at this point the JTable already contains data. I don't know what is the correct way to post to table if updating table or adding to Node and table will update automatically.

Should I update table from portScanMain class or from ipScanMain class the portscan gets initiated from the ipScanMain class once the ip scan is finished.

I know this is network knowledge but I hope someone can see the logic here.

I'm only ging to post one class since posting the whole project is pointless

/**
 * <h1>PortScanMain</h1>
 * this class is responsible for main logic of scanning
 * and detecting open ports in a host on the network
 * @author George
 * @version 1.0
 */
public class PortScanMain extends SwingWorker<Void, Integer>{   

    final int MAX_PORT = 1024;  
    public Scanner in;
    public String ip;
    public Future<Node> result = null;
    public int startPort = 0;
    final int TIME_OUT = 4000;
    private Node node;
    private JTable table;
    private int hostNum = 0;
    private DefaultTableModel model;
    public PortScanCallable pScan;      
    final int NUM_OF_THREAD = MAX_PORT; //divided by 4 b/c 4 processors so 256 threads 
    public ExecutorService servicePool = Executors.newFixedThreadPool(NUM_OF_THREAD);
    public List<Future<Node>> resultList = new ArrayList<>();
    public int endPort = startPort + (MAX_PORT/NUM_OF_THREAD);
    
    
    /**
     * setter method to set ip address
     * @param ip
     */
    public PortScanMain(Node node, JTable table, int num) {
        System.out.println("Scanning " + node.getIp());
        this.node = node;
        this.table = table;
        this.hostNum = num;
    }
    
    @Override
    protected Void doInBackground() throws Exception {
        model = (DefaultTableModel) table.getModel();
        for(int i = 0; i <= NUM_OF_THREAD/2; i++) { 
            PortScanCallable portScan = new PortScanCallable(node.getIp(), startPort, endPort); //scan 2 ports @time
            result = servicePool.submit(portScan); 
            resultList.add(result);
            startPort = endPort+1; 
            endPort = startPort + (MAX_PORT / NUM_OF_THREAD);
        }
                
        try {
            Thread.sleep(TIME_OUT);
        } catch (InterruptedException e1) {
            e1.printStackTrace();
        }       
        
        //picking up results
        if(result.isDone()) {
            //print result
            System.out.println(ip + " Open ports ");
            for(Future<Node> future : resultList) {
                for(Integer port: future.get().openPorts) {
                    try {
                        if(future.get() != null) {
                            publish(port);
                        }               
                    } catch (InterruptedException | ExecutionException e) {
                        e.printStackTrace();
                    }
                }           
            }
        }
        return null;
    }

    @Override
    protected void process(List<Integer> chunks) {      
        for(Integer port : chunks) {
            System.out.println(hostNum +" "+ ip +" "+ port);
        }
    }

    @Override
    protected void done() {
        table.setValueAt("22, 80, 443", hostNum, 4);
    }
    
    /**
     * this method will initiate the thread pool and send port ranges 
     * to callable class to be scanned. then pause for 4 sec and
     * finally display results from the scanned ip adress
     * @throws InterruptedException
     * @throws ExecutionException
     */
    public void startPortScanning() throws InterruptedException, ExecutionException {
        
        
        servicePool.shutdown();
        try {
            servicePool.awaitTermination(3, TimeUnit.SECONDS);
            servicePool.shutdownNow();
        } catch (InterruptedException e) {
            
        }
    }   

}


public class PortScanCallable implements Callable<Node>{
    
    List<Integer> portsResult;
    int startPort;
    int endPort;
    Node newNode;
    String ipAddress;
    int timeOut = 1000;
    
    /**
     * Constructor for PortScanCallable. 
     * @param ipAddress
     * @param startPort
     * @param endPort
     */
    public PortScanCallable(String ipAddress, int startPort, int endPort) {
        this.ipAddress = ipAddress;
        this.startPort = startPort;
        this.endPort = endPort;
        newNode = new Node(ipAddress);
        portsResult = new ArrayList<Integer>();
        
    }

    /**
     * this method establishes a socket connection
     * to each port and if port is open, 
     * then adds to result
     * @return newNode
     */
    @Override
    public Node call() throws Exception {
        for (int i = startPort; i <= endPort; i++) {
            try {
                //establishing connection to every port
                Socket socket = new Socket();
                SocketAddress address = new InetSocketAddress(ipAddress, i);
                socket.connect(address, timeOut);                
                if (socket.isConnected()) {
                    System.out.println("CONNECTED: " + i);
                    socket.close();
                    newNode.openPorts.add(i);
                }
            } catch (UnknownHostException e) {
                //e.printStackTrace();
            } catch (SocketTimeoutException e) {
                //e.printStackTrace();
            } catch (ConnectException e) {
                //e.printStackTrace();
            } catch (IOException e) {
                //e.printStackTrace();
            }
        }
        
        return newNode;
    }

}
MadProgrammer
  • 343,457
  • 22
  • 230
  • 366
miatech
  • 2,150
  • 8
  • 41
  • 78
  • Since I'm assuming you're going to associate the ports with the `Node`, you need to update trigger an update to the `JTable` which tells it that the row which represents the `Node` has changed. This would be better done via the `TableModel` (or `AbstractTableModel` as it already supports the creation of `TableEvent`s) – MadProgrammer Apr 23 '23 at 20:45
  • @MadProgrammer trigger? don't know what that means. is that a method? could you explain with some code? – miatech Apr 23 '23 at 22:21
  • You update the `JTable` by having the `TableModel` trigger an appropriate change event - for [example](https://stackoverflow.com/questions/13753562/adding-progress-bar-to-each-table-cell-for-file-progress-java/13755155#13755155). You should see [How to Use Tables](https://docs.oracle.com/javase/tutorial/uiswing/components/table.html), in particular [Listening for Data Changes](https://docs.oracle.com/javase/tutorial/uiswing/components/table.html#modelchange) and [Firing Data Change Events](https://docs.oracle.com/javase/tutorial/uiswing/components/table.html#fire) – MadProgrammer Apr 23 '23 at 22:24

0 Answers0