How to prevent a Java app from binding to a socket that another process is already bound to on Windows?
I have an issue where I have a Java application that is listening on port 80. The application starts fine and reports no exceptions. I couldn't figure out why I couldn't connect on port 80. Other ports worked fine. I checked netstat for other processes listening on 80 and found Skype. I didn't think that was possible, but after some research, I'm guessing Skype is listening with the SO_REUSEADDR option. In this state the accepting application is indeterminate. I would like my Java application to fail in this instance with a bind exception (or other).
It looks like I could use SO_EXCLUSIVEADDRUSE if I had access to that option via Java but I don't think that is possible. There are lots of questions and answers around SO_REUSEADDR but none that I could find that answered my question. This isn't just about Skype (I can turn off the listening part), I want my program to be more robust in this situation.
This is snippet from netstat -abn on a Windows 7 box:
Proto Local Address Foreign Address State
TCP 0.0.0.0:80 0.0.0.0:0 LISTENING [java.exe]
TCP 0.0.0.0:80 0.0.0.0:0 LISTENING [Skype.exe]
This is why I'm assuming that Skype is using SO_REUSEADDR
The processes don't appear to be listening on different interfaces.
Here is a snippet of the code. The port is 80:
myServerSocket = new ServerSocket(myTcpPort);
while (true) {
new HTTPSession( myServerSocket.accept(), threadPool );
}
As further information I created a sample program to minimize any side effects or mishandled messages.
import java.net.ServerSocket;
public class PortTest
{
public static void main(String[] args)
{
System.out.println( "Hit Ctrl-C to stop.\n" );
try {
ServerSocket myServerSocket = new ServerSocket(80);
System.out.println( "Before the accept() call.");
myServerSocket.accept();
System.out.println( "After the accept() call." );
}
catch (Exception ex ) {
System.out.println("Error listening.");
ex.printStackTrace();
}
}
}
I still don't get an exception when running this sample program (PortTest) and when Skype is running and listening on port 80. And to further test, I executed a second instance PortTest and I do see the port in use message.
Error listening.
java.net.BindException: Address already in use: JVM_Bind
at java.net.DualStackPlainSocketImpl.bind0(Native Method)
at java.net.DualStackPlainSocketImpl.socketBind(Unknown Source)
at java.net.AbstractPlainSocketImpl.bind(Unknown Source)
at java.net.PlainSocketImpl.bind(Unknown Source)
at java.net.ServerSocket.bind(Unknown Source)
at java.net.ServerSocket.<init>(Unknown Source)
at java.net.ServerSocket.<init>(Unknown Source)
at PortTest.main(PortTest.java:10)
The Error “address already in use” occurred because some process was already running on the same port. So we can resolve the issue just by killing the process. To stop the process, we need the process ID (PID), which we can fetch using the lsof command.
No, you don't need to bind(). If you're using a TCP or UDP socket where you are planning to either connect() or send a packet to a destination with sendto(), the kernel will automatically bind the socket to a suitable port number when you try to connect or send.
Is it possible to bind one process to multiple ports? Yes. Yes, each listening (bound) port is serviced by a separate socket (as are all the connections made from each listening port). Thanks for the answer.
If a socket has an IP address but not a port number it is said to be 'unbound'.
socket = new ServerSocket(0);
Will automatically select you a free port.
Furthermore, this code will tell you wether a port is avaliable:
boolean portAvaliable = true;
ServerSocket s = null;
try {
s = new ServerSocket(yourPort);
}
catch (IOException e) {
portAvaliable = false;
}
finally {
if (s != null)
try {
s.close();
}
catch (IOException e) {
//handle the exception
}
}
Check the boolean value from portAvaliable
in order to identify the port status.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With