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