I try to check if port 80 is available using the following method :
Sockets: Discover port availability using Java
I have a Java application that checks if port 80 is available, if so, it runs a small web server listening on port 80. It works great to detect if another Java application listens on port 80, e.g. if I run my application two times, the second instance will correctly tell me that the port 80 is being used.
The problem is that I have WAMP running and listening on port 80, and that if I run my Java application after I started WAMP, it won't tell me that the port 80 is busy. It seems that it only tells me if another Java application uses the port 80.
That goes beyond my understanding ... any help is greatly appreciated!
Code snippet:
int port = 80;
if(!Connection.isPortAvailable(port)) {
logger.info("Port " + port + " is already in use");
}
// in Connection class
public static boolean isPortAvailable(int port) {
ServerSocket ss = null;
DatagramSocket ds = null;
try {
ss = new ServerSocket(port);
ss.setReuseAddress(true);
ds = new DatagramSocket(port);
ds.setReuseAddress(true);
return true;
} catch (IOException e) {
} finally {
if (ds != null) {
ds.close();
}
if (ss != null) {
try {
ss.close();
} catch (IOException e) {
/* should not be thrown */
}
}
}
return false;
}
The correct answer to all questions of this nature is to try to use it and catch the exception. Not try to see if it's available and then try to use it and still have to handle the exception, which has several obvious problems:
There is a timing window between 'see' and 'try' during which the situation can change (both ways).
You still have to catch failures in the 'use' part anyway.
It is basically just trying to predict the future. This is supposed to be computer science, not fortune-telling.
This applies to most values of 'it', including network ports, files, any resource really.
I was able to reproduce your problem by running WampServer (verified that it was running by visiting localhost:80) and running a minimal java program given your example code.
The code in the try block did not throw an exception when WampServer was running. However, modify the first few lines of the try block like this
ss = new ServerSocket();
ss.bind(new InetSocketAddress("127.0.0.1", port));
and isPortAvailable will properly detect when WampServer is running and when it is not. Using "0.0.0.0" instead of "127.0.0.1" didn't work with WampServer, but did properly detect when IIS was running. You can check both by closing the first socket
ss = new ServerSocket();
ss.bind(new InetSocketAddress("0.0.0.0", port));
ss.close();
ss = new ServerSocket();
ss.bind(new InetSocketAddress("127.0.0.1", port));
Related
I am experiencing an error which I am at a loss to explain. I feel like I'm so close but I just can't seem to get a connection.
I have setup two RMI server objects on a remote server and I want to connect to and use these. I am able to connect to the RMIRegistry on the server on port 1099 and with the call Registry.list() I get the correct names of the stubs which are setup on the server.
Now for my code...
Server object 1
Registry registry = null;
try {
registry = LocateRegistry.createRegistry(1099);
} catch (RemoteException e){
System.out.println("Registry already exists - connecting...");
try {
registry = LocateRegistry.getRegistry(1099);
String[] objects = registry.list();
for (int n=0; n<objects.length; n++){
System.out.println(objects[n]);
}
} catch (RemoteException ex) {
ex.printStackTrace();
System.out.println("RMI registry connection fail.");
System.exit(1);
}
}
BioBingoLogic bb = null;
bb = new BioBingoLogic();
BioBingoInterface bbStub = null;
try {
bbStub = (BioBingoInterface)
UnicastRemoteObject.exportObject(bb, 9753);
} catch (RemoteException e){
e.printStackTrace();
System.out.println("RemoteServer export fail.");
System.exit(1);
}
try {
registry.rebind("BioBingoServer", bbStub);
} catch (RemoteException e){
e.printStackTrace();
System.out.println("Registry rebind fail.");
System.exit(1);
}
Server object 2
Completely the same as Server object 1 only exported on port 9754 and called "DatabaseServer".
Output
My output from these two objects is in the following picture:
Output from running the two server objects.
Client side
The server objects work as I expect them to. It is the Client which doesn't seem to be able to connect to the individual server objects.
System.out.println("Creating RMI Registry stub.");
Registry remoteRegistry = null;
try {
remoteRegistry = LocateRegistry.getRegistry("biobingo", 1099);
String[] objects = remoteRegistry.list();
System.out.println("\nObjects in stub:");
for (int n = 0; n < objects.length; n++) {
System.out.println(objects[n]
}
System.out.println();
System.out.println("Connecting to BioBingoServer object.");
try {
game = (BioBingoInterface) remoteRegistry.lookup("BioBingoServer");
db = (DatabaseInterface) remoteRegistry.lookup("DatabaseServer");
} catch (Exception e) {
e.printStackTrace();
System.out.println("Stub not found.");
System.exit(1);
}
} catch (RemoteException e) {
e.printStackTrace();
System.out.println("Registry not found.");
System.exit(1);
}
System.out.println("Connected to BioBingoServer.");
System.out.println("Connected to DatabaseServer");
biobingo is the IP of the remote server registered with the alias in my hosts file.
Output
This is where the problem arises....
I get the output in the following picture:
Output from client side application
It should be understood from the picture, that I never get an exception of any kind. It just hangs on the call Registry.lookup() until it, I suppose, gets a timeout from the server and executes the next part of the client code - calls to the server object then throws a RemoteException.
It should be noted that the remote server is behind a NAT, however, the NAT and its firewall is setup to allow all incoming TCP traffic, from all IP's, on all the specified ports; 1099 + 9753 + 9754.
I have also verified that the ports are indeed open with a port scanner.
This is where I am at a loss...
Any suggestions to what is preventing me from connecting to the server objects, when I am entirely able to connect to the RMIRegistry?
Any help is greatly appreciated - thank you!
---------------------------------------------
EDIT
---------------------------------------------
I tried running the server objects and client with the java vm option:
-Dsun.rmi.transport.tcp.logLevel=VERBOSE
The following picture shows the output and includes description of the flow and where the possible error occurs:
output with java vm option.
Client output
No output, just a 3 minute delay on Registry.lookup(). Afterwards the following code is executed and then on function calls to the RMI stub there’s a 3 minute delay followed by a ConnectException saying *connection timed out to 10.230.56.71` (which is the local IP of the server, although I’m connecting to it’s global IP - so it seems that my call does find it’s way to the NAT which the server is behind).
Server output
Nothing, really.
I'm wanting to use Java to check if a server that's in a state of booting up is reachable yet via SSH (port 22). Currently, I'm just looping using the isReachable method like so ...
reachable = InetAddress.getByName(host).isReachable(timeout);
But this of course doesn't specifically check SSH port 22, so my Java application may jump the gun and try to SSH into the host when it's "reachable" but not necessarily via SSH. Any recommendations for how best to check if a server is ready to be SSH'ed into?
In order to specifically check for port 22, you could use standard Java Sockets, e.g.:
Socket socket = null;
boolean reaching = false;
try {
socket = new Socket("yourserver.com", 22);
reaching = true;
}catch(Exception e){
reaching = false;
}finally{
if(socket != null){
try {
socket.close();
}catch(IOException e){}
}
}
System.out.println(reaching);
In order to avoid unpleasant blocking, you could also set a timeout:
try {
int timeout = 3000; // timeout in ms
socket = new Socket();
socket.connect(new InetSocketAddress("yourserver.com",22), timeout);
reaching = true;
} catch(Exception e) {
reaching = false;
}
I am trying to build a port scanner which not only scans for port numbers but, also list the services running on the respective port .I am new to java-programming and As you can see i have the code for scanning the status of ports on the local machine. I don't know where to start when it comes to list services running on each port. I would appreciate if anyone can suggest me any code/links to list those services. Thanks for the help.....
public class port {
public static void main(String[] args) throws Exception {
String host = "localhost";
InetAddress inetAddress = InetAddress.getByName(host);
String hostName = inetAddress.getHostName();
for (int port = 0; port <= 200; port++) {
try {
Socket socket = new Socket(hostName, port);
String text = hostName + " is listening on port " + port;
System.out.println(text);
socket.close();
}
catch (IOException e)
{
String s = hostName + " is not listening on port " + port;
System.out.println(s);
}
}
}
}
The code seems fine if you want to check for open ports, but identifying services... well, that's tricky.
It's a bit like identifying the type of file by reading the first few bytes. An easy solution is to compare the port number with the list of well known ports. So if port 80 is open, you just assume it's HTTP and move on.
This method assumes that services actually listen on their assigned ports. This is like assuming that a file that ends with "zip" is always a zip file. It's correct most of the time, but only because it's a convention. Not because it has to be this way. If you want to actually fingerprint services - determine the type of service by "talking to it", then it's a serious undertaking, not something that can be explained in a few lines. I suggest you take a look at Nmap, as it's an existing tool that does just that. You might be able to use it instead of writing your own.
So, you are looking for something like Nmap?
Your code seems good to me, although I would do something like
public class PortScanner {
public static void main(String[] args) throws Exception {
final String host = "localhost";
final InetAddress inetAddress = InetAddress.getByName(host);
final String hostName = inetAddress.getHostName();
final List<int> openPorts = new ArrayList();
// we begin at port 1 because port 0 is never used
for (int port = 1; port <= 200; port++) {
try {
Socket socket = new Socket(hostName, port);
openPorts.add(port);
} catch (IOException) {
} finally {
socket.close();
}
}
}
}
You cannot easily know what service is running on the port, you can only simply assume what service is running on that port using this list. But beware, a web server can use custom ports instead of default ones.
If you do have the requirement to know exactly what service is running on what port, I suggest you use Nmap and make a bash script out of it which in turn outputs it's findings in a .txt file. That .txt file can then be read by Java. This approach saves tons of work.
I have an Eclipse plugin that needs to open a pair of sockets to a flash application running on the local machine. Flash requires a policy file (blob of XML) giving permissions to access the ports in question. Flash prefers to get this policy file over port 843, Java treats ports < 1024 as privileged ports and Mac OS X and Linux similarly restrict access to ports < 1024. I don't want to run my Eclipse plugin with root permissions, so serving up the policy file on port 843 is not an option. According to Adobe documentation, if Flash can't get the policy file on port 843, it falls back to requesting the policy file on the port to which it's trying to connect. The ActionScript code looks like this:
/**
* Connecting to some port to communicate with the debugger. We initiate the
* connection because Flex doesn't allow us to listen to any ports.
*/
private function initSockets():void
{
requestSocket = new Socket();
requestSocket.addEventListener(Event.CONNECT, requestConnected);
requestSocket.addEventListener(Event.CLOSE, closed);
requestSocket.addEventListener(ProgressEvent.SOCKET_DATA, processRequestData);
requestSocket.addEventListener(IOErrorEvent.IO_ERROR, ioError);
requestSocket.addEventListener(SecurityErrorEvent.SECURITY_ERROR, securityError);
requestSocket.connect("localhost", SCConstants.DEBUG_LESSON_REQUEST_PORT);
eventSocket = new Socket();
eventSocket.addEventListener(Event.CONNECT, eventConnected);
eventSocket.addEventListener(Event.CLOSE, closed);
eventSocket.addEventListener(ProgressEvent.SOCKET_DATA, processEventData);
eventSocket.addEventListener(IOErrorEvent.IO_ERROR, ioError);
eventSocket.addEventListener(SecurityErrorEvent.SECURITY_ERROR, securityError);
eventSocket.connect("localhost", SCConstants.DEBUG_LESSON_EVENT_PORT);
}
On the Eclipse plugin side I've inherited some code that works most of the time on OS X, but sometimes fails on Windows. Running on Wi-Fi rather than wired ethernet also tends to fail, although I have no idea why this should matter.
public Boolean connect() throws DebugException {
try {
try {
// connection code
fRequestServerSocket = new ServerSocket(requestPort);
fRequestServerSocket.setSoTimeout(ACCEPT_TIMEOUT);
fEventServerSocket = new ServerSocket(eventPort);
fEventServerSocket.setSoTimeout(ACCEPT_TIMEOUT);
TWBLogger.logInfo("Open socket request server:" + fRequestServerSocket);
TWBLogger.logInfo("Open socket event server:" + fEventServerSocket);
String policy = "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n" +
"<cross-domain-policy>\n" +
"<allow-access-from domain=\"*\" to-ports=\"5000,5001\" secure=\"false\" />\n" +
"</cross-domain-policy>\0";
// Because of the Flash security policy the first thing
// that will accept on the socket will be the Flash Player
// trying to verify us. The Flash player will request security
// policy file with the following string: <policy-file-request/>\0
// We will serve back the above policy file and then close the socket
// The next thing to accept is our process in the VM.
fRequestSocket = fRequestServerSocket.accept();
fRequestWriter = new PrintWriter(fRequestSocket.getOutputStream());
fRequestReader = new BufferedReader(new InputStreamReader(fRequestSocket.getInputStream()));
// Wait some time before giving flash the policy file. Otherwise they don't get it. ;(
// 3 is too much ... ;(
Thread.sleep(100);
fRequestWriter.print(policy);
fRequestWriter.flush();
fRequestSocket.close();
// this should be the real connection
fRequestSocket = fRequestServerSocket.accept();
TWBLogger.logInfo("Open socket request:" + fRequestSocket);
fRequestWriter = new PrintWriter(fRequestSocket.getOutputStream());
fRequestReader = new BufferedReader(new InputStreamReader(fRequestSocket.getInputStream()));
// the same situation for the EventSocket
fEventSocket = fEventServerSocket.accept();
fEventReader = new BufferedReader(new InputStreamReader(fEventSocket.getInputStream()));
TWBLogger.logInfo("Open socket event:" + fEventSocket);
} catch (SocketTimeoutException e) {
TWBLogger.logWaring("Connection to the Client Timed out.");
cleanSockets();
return false;
requestFailed("Connection to the VM timed out. Please close any other running lessons that you debug and try again", e);
} catch (SocketSecurityException e) {
requestFailed("Security error occured when connecting to the VM", e);
} catch (Exception e) {
if (!fTerminated)
requestFailed("Error occured when connecting to the VM. Please close any other running lessons that you debug.", e);
}
} catch (DebugException e) {
// close the sockets so that we can debug another application
cleanSockets();
throw e;
}
// our VM is single threaded
fThread = new TWBThread(this);
fThreads = new IThread[] {fThread};
// start listening for events from the VM
fEventDispatch = new EventDispatchJob();
fEventDispatch.schedule();
// start listening for breakpoints
IBreakpointManager breakpointManager = getBreakpointManager();
breakpointManager.addBreakpointListener(this);
breakpointManager.addBreakpointManagerListener(this);
return true;
}
This code looks wrong. It doesn't wait for the message from Flash and instead just jams the policy response into the port. As I said, it works most of the time, but it fails sometimes and doesn't seem to comply with Adobe's documentation.
I tried listening for request packets on each port and sending a port specific response. I watched socket traffic using WireShark on the loopback interface (Mac OS X). I saw policy requests coming in and responses getting sent, but Flash still gave me Security Sandbox Violation on both ports.
I also tried adding this line at the beginning of initSockets shown above:
Security.loadPolicyFile("xmlsocket://localhost:5002");
Then I added code in my plugin to listen on port 5002 and send the following master policy file content:
private final static String FLASH_POLICY_RESPONSE =
"<?xml version=\"1.0\"?>\n" +
"<!DOCTYPE cross-domain-policy SYSTEM \"/xml/dtds/cross-domain-policy.dtd\">\n" +
"<cross-domain-policy>\n" +
"<site-control permitted-cross-domain-policies=\"master-only\"/>\n" +
"<allow-access-from domain=\"*\" to-ports=\"5000,5001\"/>\n" +
"</cross-domain-policy>\0";
Again I saw the request come in and the response go out, but Flash didn't seem to respond to it. I didn't get the Security Sandbox Violation errors, but there was also no traffic over the ports.
Can anyone enlighten me on the correct approach to opening sockets between Java and Flash?
I found the solution to this. I made a mistake early on and used BufferedReader.readLine to read the policy request. This isn't appropriate since policy requests are null terminated, not new line terminated. This was confusing since it does return when the underlying stream closes. Thus I got the request and sent a response, but the response was sent after the ActionScript code had already decided that the request had failed.
On the Java side I used the following code to establish communication on the ports:
// Create server sockets.
fRequestServerSocket = new ServerSocket(REQUEST_PORT);
fRequestServerSocket.setSoTimeout(ACCEPT_TIMEOUT);
TWBLogger.logInfo("Open socket request server:" + fRequestServerSocket);
fEventServerSocket = new ServerSocket(EVENT_PORT);
fEventServerSocket.setSoTimeout(ACCEPT_TIMEOUT);
TWBLogger.logInfo("Open socket event server:" + fEventServerSocket);
// Serve up the Flash policy file.
serveFlashPolicy();
// Connect request socket.
fRequestSocket = fRequestServerSocket.accept();
TWBLogger.logInfo("Open socket request:" + fRequestSocket);
fRequestWriter = new PrintWriter(fRequestSocket.getOutputStream());
fRequestReader = new BufferedReader(new InputStreamReader(fRequestSocket.getInputStream()));
// Connect event socket.
fEventSocket = fEventServerSocket.accept();
TWBLogger.logInfo("Open socket event:" + fEventSocket);
fEventReader = new BufferedReader(new InputStreamReader(fEventSocket.getInputStream()));
Serving up the policy file is handled as follows:
private void serveFlashPolicy() {
ServerSocket serverSocket = null;
Socket socket = null;
TWBLogger.logInfo("Waiting for flash policy request on port " + FLASH_POLICY_PORT);
try {
serverSocket = new ServerSocket(FLASH_POLICY_PORT);
serverSocket.setSoTimeout(ACCEPT_TIMEOUT);
socket = serverSocket.accept();
PrintWriter writer = new PrintWriter(socket.getOutputStream());
BufferedReader reader = new BufferedReader(new InputStreamReader(socket.getInputStream()));
StringBuilder request = new StringBuilder();
int c;
while (0 < (c = reader.read())) {
request.append((char) c);
}
String policyRequest = request.toString();
if (policyRequest.startsWith(FLASH_POLICY_REQUEST)) {
writer.print(FLASH_POLICY_RESPONSE);
writer.print("\0");
writer.flush();
}
} catch (IOException e) {
TWBLogger.logWaring("IOException on port " + FLASH_POLICY_PORT + ": " + e.toString());
e.printStackTrace();
} finally {
if (null != socket) {
try {
socket.close();
} catch (Exception e) {
// Ignore
}
}
if (null != serverSocket) {
try {
serverSocket.close();
} catch (Exception e) {
// Ignore
}
}
}
TWBLogger.logInfo("Flash policy complete on port " + FLASH_POLICY_PORT);
}
The Flash policy response looks like this:
private final static String FLASH_POLICY_RESPONSE =
"<?xml version=\"1.0\"?>\n" +
"<!DOCTYPE cross-domain-policy SYSTEM \"/xml/dtds/cross-domain-policy.dtd\">\n" +
"<cross-domain-policy>\n" +
"<allow-access-from domain=\"*\" to-ports=\"5000,5001\"/>\n" +
"</cross-domain-policy>";
The site-control tag I had previously been sending is only allowed in master policy files served from port 843.
How can I check service using java? I found this article, but it is only for checking hostname.
My question is how can I check is service on port x running, ex: myhostname:8080 or myhostname:8099 , I might be running service n or p on those ports but it would be visible trough web if I do it manually, how can I achieve same effect in java?
That snippet sends a ping, which you can't manipulate to achieve what you want. Just open a socket and catch any exceptions.
bool success = true;
try {
(new Socket(host, port)).close();
} catch (UnknownHostException e) {
// unknown host
success = false;
} catch (IOException e) {
// io exception, service probably not running
success = false;
}
If you need to detect which service is running, then you need to read the first bytes sent and compare them to what you know each service should send. This might require a few passes back and forth.
Since your services are web, you might want to add a verification of the response code.
boolean available = false;
HttpURLConnection conn = null;
try {
conn = (HttpURLConnection) new URL("http://yourdomain/").openConnection();
conn.connect();
if(conn.getResponseCode() == 200)
available = true;
}
catch(IOException e) {
}
finally {
if(conn != null)
conn.disconnect();
}
Just attempt to connect to the socket.
InetAddress addr = InetAddress.getByName("myhostname");
Socket socket = new Socket(addr, 8099);
If that doesn't thrown an exception then the host is accepting connections on that port. If it isn't you'll typically get a ConnectException.
Just attempt to use the service and deal with the exceptions as they arise. There's generally no point in testing any resource for availability prior to using it. What if it was available when you tested and not when you used it?
You can use sockets to do this.
new Socket("localhost", 8080).getInputStream()
Surround that with a try catch block and you have a solution.