Monday, July 20, 2009

Testing opened socket in Vista, weird issue!

How do you test that there is some service listening on given port in Java? How do you learn that given port is free and you can start your own service there?

It seems that the Java Socket class can be used to find the answers to such questions. The most simple example would be to create a new instance using new Socket("localhost",port_number). If this socket can be instantiated and connected to given port then it is used by existing service, if not, you get an exception and you know that it is probably free. Not only similar approach is recommended in many articles on the web but it is also used in apache commons net (see here).

Now, I realized that this approach does not work on my Windows Vista Business SP1 (32-bit). It seems that under my Vista the Java thinks that any port is already taken and connection can be opened... wow!

The following is a simple java code which fails on Ubuntu and Windows 98, but passes on my Windows Vista (it should fail!) running under Java 1.5:

package somePackage;

import java.io.IOException;
import java.net.ServerSocket;
import java.net.Socket;
import java.net.UnknownHostException;

public class SocketWorksOnVista {

public static void main(String[] args) {

Socket client = null;
ServerSocket server = null;
try {

// first let's test that we can open a socket at given port
server = new ServerSocket(4444);
System.out.println("server bound? " + server.isBound());
// close it for now
server.close();
System.out.println("server closed? " + server.isClosed());
// now, there is nothing running on port 4444

client = new Socket("localhost",4444);
System.out.println(client.getRemoteSocketAddress());

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

if (client != null) {
System.out.println("Is connected? " + client.isConnected());
try {
client.close();
System.out.println("connection closed");
} catch (IOException e) {
e.printStackTrace();
}
} else {
System.out.println("connection not established!");
}
}
}
}
Does anybody know what is wrong with this code? Why the following line: client = new Socket("localhost",4444) does not fail in Vista? Is there a bug in Java?

Note: I did test port availability using netstat -an | grep 4444 (using Cygwin) prior and after the test and I am sure there is no service running on my computer on 4444. If there were already running any service then the code would fail at the very beggining when trying to create a new ServerSocket instance. Also I did test different port numbers as well.

3 comments:

Tomáš Hubálek said...

It looks like firewall issue. I would doublecheck all firewall/antivirus settings.

kimchy said...

I have noticed something similar in windows as well. For example, you can start two jetty instances on the same port in windows (xp/vista).

p.s. The main problem with creating a socket on the mentioned port to check if it is already taken is the fact that closing it will not necessarily close it on the operating system side, so other code that will try and assume that this port is open because of the mentioned code will fail to open a server side socket on it.

Shay

Lukáš Vlček said...

In my case this socket checking code was a part of a logic which was used to determine if a server can be started or not (initialization of test case). I was sure there was no service running on the used port number so I commented out this socket check and the test passed: it started server on given port, deployed application into, undeployed and stopped the server. I think this wouldn't be possible if the port was really taken (I tried to start the server twice and the second attempt failed - it was not a jetty server but JBoss).