I am writing a port scanner in Java and I want to be able to distinct the following 4 use cases:
- port is open
- port is open and server banner was read
- port is closed
- server is not live
I have the following code:
InetAddress address = InetAddress.getByName("google.com");
int[] ports = new int[]{21, 22, 23, 80, 443};
for (int i = 0; i < ports.length; i++) {
int port = ports[i];
Socket socket = null;
try {
socket = new Socket(address, port);
socket.setSoTimeout(500);
System.out.println("port " + port + " open");
BufferedReader reader = new BufferedReader(
new InputStreamReader(socket.getInputStream()));
String line = reader.readLine();
if (line != null) {
System.out.println(line);
}
socket.close();
} catch (SocketTimeoutException ex) {
// port was open but nothing was read from input stream
ex.printStackTrace();
} catch (ConnectException ex) {
// port is closed
ex.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
} finally {
if (socket != null && !socket.isClosed()) {
try {
socket.close();
} catch (Exception e) {
e.printStackTrace();
}
}
}
}
The problem is that I get a ConnectionException both when the port is closed and the server cannot be reached but with a different exception message:
java.net.ConnectException: Connection timed out: connect
when the connection was never established and
java.net.ConnectException: Connection refused: connect
when the port was closed
so I cannot make the distincti开发者_C百科on between the two use cases without digging into the actual exception message.
Same thing happens when I try a different approach for the socket creation. If I use:
socket = new Socket();
socket.setSoTimeout(500);
socket.connect(new InetSocketAddress(address, port), 1000);
I have the same problem but with the SocketTimeoutException instead. I get a
java.net.SocketTimeoutException: Read timed out
if port was open but there was no banner to be read and
java.net.SocketTimeoutException: connect timed out
if server is not live or port is closed.
Any ideas? Thanks in advance!
I don't think you have any options besides parsing the exception message. Is there a reason you'd rather not do this?
ConnectException only has an empty constructor and an errorMesssage constructor. There are no subclasses of ConnectException in the API. So I am afraid, Java does no proper way to access the reason. Parsing the exception message seems to be the only way, despite it being really messy with translations.
精彩评论