In Java you can give the number zero as a single parameter for the Socket or DatagramSocket constructor. Java binds that Socket to a free port then. Is it possible to limit the port lookup to a specific range?
Hrm, after reading the docs, I don't think you can. You can either bind to any port, then rebind if it is not acceptable, or repeatedly bind to a port in your range until you succeed. The second method is going to be most "efficient".
I am uneasy about this answer, because it is... inelegant, yet I really can't find anything else either :/
Binding the socket to any free port is (usually) a feature of the operating system's socket support; it's not specific to java. Solaris, for example, supports adjusting the ephemeral port range through the ndd command. But only root can adjust the range, and it affects the entire system, not just your program.
If the regular ephemeral binding behavior doesn't suit your needs, you'll probably have to write your own using Socket.bind().
Here's the code you need:
public static Socket getListeningSocket() {
for ( int port = MIN_PORT ; port <= MAX_PORT ; port++ )
{
try {
ServerSocket s = new ServerSocket( port );
return s; // no exception means port was available
} catch (IOException e) {
// try the next port
}
}
return null; // port not found, perhaps throw exception?
}
You might glance at the java code that implements the function you are using. Most of the java libraries are written in Java, so you might just see what you need in there.
Assuming #Kenster was right and it's a system operation, you may have to simply iterate over ports trying to bind to each one or test it. Although it's a little painful, it shouldn't be more than a few lines of code.
Related
I am creating a simple learning project (chat using sockets) in Java and today I faced a problem. Maybe the point is an obvious one for somebody, but I am confused with it
The purpose
To get to know (at least one of the following):
A list of the currently opened free/taken ports on a PC
Whether the port I want to use is locked
What I tried
I've created a simple raw-project and run two ServerSocket on one port. In this case I have caught a java.net.BindException with notification that "...Address already in use: JVM_Bind...". But in this way I am able to check the port avaliability only if my JVM has captured it. In case if other program listens to the port, I do not know anything about it. I am adding a code below.
public class Main {
public static void main(String[] args) throws IOException {
MyThread myThread = new MyThread();
ServerSocket serverSocket = new ServerSocket(5940);
myThread.start();
serverSocket.accept();
}
}
public class MyThread extends Thread {
#Override
public void run() {
try {
ServerSocket serverSocket = new ServerSocket(5940);// exception is thrown here
serverSocket.accept();
} catch (IOException e) {
System.err.println("SECOND SERVER");
e.printStackTrace();
interrupt();
}
}
}
PS Any advice is warmly welcomed
I've created a simple raw-project and run two ServerSocket on one
port. In this case I have caught a java.net.BindException with
notification that "...Address already in use: JVM_Bind...". But in
this way I am able to check the port avaliability only if my JVM has
captured it. In case if other program listens to the port, I do not
know anything about it.
I think you're misinterpreting your result. I have every reason to believe that if the port you request is already bound by any process then your attempt to bind it will fail with a BindException. That takes care of
Whether the port I want to use is locked
. As for
A list of the currently opened free/taken ports on a PC
, there are system utilities that can get you that information, but it is useless to you. Whichever end initiates the connection (i.e. the client) needs to know in advance what port to try to connect to. It cannot get that from the server, because that presents a chicken & egg problem.
The usual approach is that the server listens to a specific port chosen by its developer or its admin, and that port number is provided to clients out of band -- often simply by it being a standard, well-known port number. That's how most of the basic network protocols work; for example, HTTP servers run on port 80 by default. If the wanted port happens to be unavailable when the server attempts to bind to it then that indicates a misconfiguration of the machine, and the server simply fails to start.
The client, on the other hand, does not need to choose a port number at all. The system will choose one for it automatically when it attempts to connect to the server.
What's the connection timeout of a socket created with a connecting constructor?
In Java SE 6, the following constructors for Socket will connect the socket right away instead of you having to call connect on it after construction:
Socket(InetAddress address, int port)
Socket(InetAddress host, int port, boolean stream)
Socket(InetAddress address, int port, InetAddress localAddr, int localPort)
Socket(String host, int port)
Socket(String host, int port, boolean stream)
Socket(String host, int port, InetAddress localAddr, int localPort)
While it's nice and convenient and all that the Java SE folks created 500 ways of constructing a socket so you can just browse the list of 500 to find the one that sort of does what you want (instead of calling new Socket() followed by Socket#connect()), none of the docs of these constructors says what the connection timeout is or whether/how they call connect(SocketAddress endpoint, int timeout).
Perhaps the stuff in the constructor docs talking about createSocketImpl imply something about the timeout, or some docs somewhere else say it?
Anyone know what the actual connection timeout for any of these constructors is?
Background: Okay, assuming the spec is really ambiguous (I thought Java is portable?), I'm trying to figure out why a customer's code freezes at seemingly random times. I have some code that calls some open source library which calls one of these constructors. I want to know whether calling one of these constructors would have made the timeout infinite or very long. I don't know what version of the JDK the customer is using so it would be nice if the spec says the timeout somewhere. I guess I can probably get the JDK version from my customer, but it will probably be the closed source JDK. In that case, could I reverse-engineer the code in their version of the SE library to find out? Is it hard? Will I go to jail?
Java spec is bogus. It doesn't say what timeout is on any of those constructor so implementation could set timeout to 0.000000000001 nanoseconds and still be correct. Furthurmore: non finite timeout not even respected by vm implementations (as seen here) so look like spec doesnt even matter cause noone followed it.
Conclusion: You have to read closed source binary of customer JVM (probably illegal but you have to do what you have to do), also OS socket doc.
Even though Java docs says the timeout is infinite, it actually means that JVM will not impose any timeout on the connect operation, however OS is free to impose timeout settings on any socket operations.
Thus the actual timeout will be dependent on your OS's TCP/IP layer settings.
A good programming practice is to set timeouts for all socket operations, preferably configurable via configuration file. The advantage of having it configurable is that depending on the network load of the deployment environment, the timeout can be tweaked without re-building/re-testing/re-releasing the whole software.
Looking at the code of Socket in OpenJDK 6-b14, you can see that these constructors call connect(socketAddress, 0), which means an infinite timeout value.
According to the sources (I'm looking at 1.5_13 here, but there shouldn't be a difference), the different Socket constructors all call Socket(SocketAddress, SocketAddress, boolean) which is defined as:
private Socket(SocketAddress address, SocketAddress localAddr,
boolean stream) throws IOException {
setImpl();
// backward compatibility
if (address == null)
throw new NullPointerException();
try {
createImpl(stream);
if (localAddr == null)
localAddr = new InetSocketAddress(0);
bind(localAddr);
if (address != null)
connect(address);
} catch (IOException e) {
close();
throw e;
}
}
connect(SocketAddress) is defined as
public void connect(SocketAddress endpoint) throws IOException {
connect(endpoint, 0);
}
Hence, infinite timeout (as #Keppil already stated).
The Socket class exists since Java 1.0, but at that time, it was only possible to create sockets, which were immediately connected and it was not possible to specify a connect timeout. Since Java 1.4, it has been possible to create unconnected sockets and then specify a timeout using the connect method. I assume that someone simply forgot to clarify the documentation of the "old" constructors, specifying that these still operate without an explicit timeout.
The documentation of the connect methods with timeout parameter reads that "a timeout of zero is interpreted as an infinite timeout". This is actually incorrect as well, since it only means that no timeout is implied by the Java VM. Even with a timeout of 0, the connect operation may still timeout in the operating system's TCP/IP stack.
It's platform-dependent but it's around a minute. The Javadoc for connect() is incorrect in stating that it is infinite. Note also that the connect() timeout parameter can only be used to decrease the default, not increase it.
Our application has server/client side. The client supports both offline and online work mode.
So I need to test the client when server down, regain connective.
Question comes. How to simulate server down. Use codes to switch from down to ready, or from ready to down state.
Thanks in advance.
Joseph
update:
Actually, I could not extend the server interface to response the incorrect status. In my test scenario, the server is transparent. So incorrect url + port is a solution to do this.
But I could not modify the url when the session is valid. Another method is modify the hosts file to do this. I have to face the privilege issue in Windows.
Depends on what you mean by "server down". Possible options are:
Write a fake/dummy server that can return error messages corresponding to being down for test purposes.
Change the IP address of the server that your client looks for to a non-existing one so that it will think that the server is entirely down.
The basic idea is to mock the behavior of your server somehow. You could use mocking frameworks to do so.
You could also create manual mocks for testing purposes. Let the "proxy" of the server on the client implement this interface:
public interface IServer
{
bool foo();
}
You could create a "fake" implementation of that server and return whatever you'd like
public class FakeOfflineServer implements IServer
{
public bool foo()
{
// throw some exception here.
}
}
This approach allows you to fake different scenarios (no network connectivity, invalid credentials, etc.)
You could also use composition to switch from up to down in your tests:
public bool FakeServer implements IServer
{
private IServer offline = new FakeOfflineServer();
private IServer online = new Server();
public bool isUp = false;
private IServer getServer()
{
return isUp ? online : offline;
}
public bool foo()
{
return getServer().foo();
}
}
While testing server down, give any incorrect URL OR Port (Prefered). For recovery give the correct URL/Port.
This depends where you are testing. If you're unit testing, the best option is the mocking suggested by Bryan Menard.
If you're testing in an integration or production environment, You can actually cut the connection between you and the server.
Depending upon your operating system, you can do this in a number of ways.
For Windows based systems, Fiddler is fantastic. You can simulate almost anything, including delays on the requests and indeed just throwing requests away. It does not require admin access for Windows.
For linux based systems, one technique I've used in the past is to use a proxy server, or cut the port at operating system level. You can do this using iptables for instance:
To deny access to a particular port (25 in this case)
/sbin/iptables -I OUTPUT -p tcp --dest 127.0.0.1 --dport 25 -j DROP
and to allow it again:
/sbin/iptables --delete OUTPUT 1
You'll need root acces for this to work, but it does have the advantage that you don't need to touch your server or client configuration.
To emulate the server down case, you could write a ServerAlwaysDown class extending your actual server, but throwing ServerException (HTTP 500) for every connection.
If you want to be thorough use always the closest you have to a production environment for the tests, put client and servers in different machines and cut the connection, then restore it.
Background: I'm writing a simple UDP application to ping a beta server I manage every minute or so to tell me it is still up and running (I can't enable ping on the server for those that are wondering). I plan to run this on my phone to warn me when the server is no longer responding.
I'm trying to use the seemingly simple java.net.DatagramSocket as such:
try
{
socket = new DatagramSocket();
socket.bind(null);
}
catch (SocketException e)
{
System.out.println(e.toString());
throw e;
}
Let me also say that I have enabled the Internet permissions through the android manifest and if I remove the uses clause to do so, I get a permissions error so I'm sure that is working OK. When I download this code to an Android Virtual Device (AVD) and execute it, on the call to bind() I am presented with this exception:
03-17 19:07:39.401: INFO/System.out(338): java.net.BindException: Invalid argument
According to this documentation, the null argument is correct:
public void bind (SocketAddress localAddr)
Since: API Level 1
Binds this socket to the local address and port specified by localAddr. If this value is null any free port on a valid local address is used.
But not trusting documentation, I decided to enumerate the IP addresses on my device like this:
ArrayList<NetworkInterface> allInterfaces = Collections.list(NetworkInterface.getNetworkInterfaces());
NetworkInterface eth = allInterfaces.get(0);
InetSocketAddress addr = new InetSocketAddress(eth.getInetAddresses().nextElement(), port);
try
{
socket = new DatagramSocket();
socket.bind(addr);
}
catch (SocketException e)
{
System.out.println(e.toString());
throw e;
}
When I step through the code, it works great and I can see the two IP address on the AVD but I get the exact same exception on the bind() call. Does anybody out there see what i might be missing? I will continue to research and hopefully post a solution to my own problem, but I am hoping somebody out there will be able to shortcut this for me.
[Edited: if you saw my previous response I made the classic debugging mistake of changing two variable in one test and it was the other one that solved my problem.]
I found the problem. It is the way I'm declaring the DatagramSocket that appears to cause problems. If I use a DatagramChannel to open the DatagramSocket in the following way then the bind() call is successful.
DatagramChannel channel = DatagramChannel.open();
DatagramSocket socket = channel.socket();
I've stumbled across this problem either and have found the cause: if you call the parameterless constructor new DatagramSocket(), this creates "a UDP datagram socket which is bound to any available port on the local host using a wildcard address" (as per the API docs). So this actually means, the Socket is already bound. My "fix" for this is as follows:
SocketAddress socketAddress = new SocketAddress(yourInetAddress, yourPort);
DatagramSocket serverSocket = new DatagramSocket(null);
serverSocket.bind(socketAddress);
This explicitly creates an unbound Socket (through the DatagramSocket (SocketAddress localAddr) constructor), making it possible to bind the Socket in turn.
This is probably the more elegant solution than creating an unnecessary channel.
P.S.: Strangely enough, this is where DatagramSocket differs from a TCP ServerSocket: the parameterless constructor of the latter will create an unbound ServerSocket, not triggering this problem.
A while ago I developed a little LAN chat app. in Java which allows chatting with other hosts, send images, etc. Although it was created just for fun, now it's being used where I work.
Currently, there is no "chat server" on the app. where each client registers, updates it's status, etc. (I liked the idea of symmetric design and not depending on a server running on some other machine).
Instead, each host is a client/server which has a hosts.properties file with the hostname of the other hosts, and - for instance - broadcasts to each one of them when sending a massive message/image/whatever.
In the beginning there were just a couple of hosts, so this hosts.properties file wasn't an issue. But as the amount of users increased, the need of updating that file was a bit daunting. So now I've decided to get rid of it, and each time the app. starts, dynammically find the other active hosts.
However, I cannot find the correct way of implement this. I've tried starting different threads, each one of them searching for other hosts in a known range of IP addresses. Something like this (simplified for the sake of readability):
/** HostsLocator */
public static void searchForHosts(boolean waitToEnd) {
for (int i=0; i < MAX_IP; i+= MAX_IP / threads) {
HostsLocator detector = new HostsLocator(i, i+(MAX_IP / threads - 1)); // range: from - to
new Thread(detector).start();
}
}
public void run() {
for (int i=from; i<=to; i++)
findHosts( maskAddress + Integer.toString(i) );
}
public static boolean findHosts(String IP) {
InetAddress address = InetAddress.getByName(IP);
if ( address.isReachable(CONNECTION_TIME_OUT) )
// host found!
}
However:
With a single thread and a low value in CONNECTION_TIME_OUT (500ms) I get wrong Host Not Found status for for hosts actually active.
With a high value in CONNECTION_TIME_OUT (5000ms) and only one single thread takes forever to end
With several threads I've also found problems similar like the first one, due to collisions.
So... I guess there's a better way of solving this problem but I couldn't find it. Any advice? Thanks!
You could try UDP Broadcast to a specific port. All running instances of your app on the network could listen to that port and then respond with a message identifying them as a host.
You could do this a lot easier using UDP. Check this tutorial for examples.
Use Bonjour/Zeroconf.
The jmdns project has all you need.
For finding all hosts in lan in java execute commands from java and add the result to JList
Here is the small code that will help to you to read all hosts in lan in windows there will be other commands for other os take look at the following code
try {
Runtime rt = Runtime.getRuntime();
FileWriter write=new FileWriter("mylist.txt");
BufferedWriter writer=new BufferedWriter(write);
Process pr = rt.exec("net view");
BufferedReader input = new BufferedReader(new InputStreamReader(pr.getInputStream()));
String line=null;
String hosts="";
while((line=input.readLine()) != null) {
Thread.sleep(100);
if((!(line.equals("")))&&(!(line.equalsIgnoreCase("Server Name Remark")))&&(!(line.equalsIgnoreCase("-------------------------------------------------------------------------------")))&&(!(line.equalsIgnoreCase("The command completed successfully."))))
{
line=line.replace('\\',' ');
line=line.trim();
listModel.addElement(line);
hosts=hosts+line.trim()+",";
hosts=hosts.trim();
}
}
writer.write(hosts);
writer.close();
} catch(Exception e) {
System.out.println(e.toString());
e.printStackTrace();
}
Each host keeps track of all the hosts they have met. When you shut down, save the known hosts to file and reuse the next time you start up.
Every so many minutes, send each of the known hosts a list of all known hosts.
That way
a) No network scanning
b) A new host will spread around the network
Then when a new host joins, he just needs to know 1 other host to learn about everyone.
A host that isn't seen for a week, or is seen from a new IP is dropped from the list of updated.
You could attempt to use DNS service discovery
There seems to be a project on sourceforge (that I have not looked at, beyond doing a cursory search...)