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)
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.
For anyone wondering, Java prior to 7u25 had this problem.
Here's an excerpt from the release note of Java 7u25:
Change in Networking API Implementation on Windows platforms
The
implementation of the networking APIs has been changed on Windows to
use the SO_EXCLUSIVEADDRUSE socket option by default. This change is
necessary to address anomalies that arise when using both IPv4 and
IPv6 applications that require to bind to the same port.
The problem is exclusive to Windows because of the funky way[1] SO_REUSEADDR[2] works there.
[1] https://msdn.microsoft.com/en-us/library/windows/desktop/ms740621(v=vs.85).aspx
[2] Socket options SO_REUSEADDR and SO_REUSEPORT, how do they differ? Do they mean the same across all major operating systems?
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.
Definitions
Well-known Port Port number in the range [0, 1023]
Registered Port Port number in the range [1024, 49151]
Dynamic Port Port number in the range [49152, 65535]
I am attempting to create a SocketServer object. When I allow SocketServer to select a dynamic port (by binding to port 0), it works as expected. If I explicitly specify a registered port, it works as expected. However, when I specify a dynamic port, it is always throwing a BindException with the message "Address already in use: JVM_Bind". The top of the stack trace for the exception is:
at java.net.DualStackPlainSocketImpl.bind0(Native Method)
at java.net.DualStackPlainSocketImpl.socketBind(DualStackPlainSocketImpl.java:106)
at java.net.AbstractPlainSocketImpl.bind(AbstractPlainSocketImpl.java:387)
at java.net.PlainSocketImpl.bind(PlainSocketImpl.java:190)
at java.net.ServerSocket.bind(ServerSocket.java:375)
at java.net.ServerSocket.<init>(ServerSocket.java:237)
at java.net.ServerSocket.<init>(ServerSocket.java:128)
I am using JDK 1.8u74 on a Windows 7 Enterprise SP1 x64 machine. The code is as follows:
SocketServer createServer(final int port) throws IOException {
// Create a new socket server
SocketServer server;
try {
// Try to bind to all interfaces
server = new ServerSocket(port, 1, null);
} catch (BindException e) {
// If that fails, try to bind to the primary IP address
final InetAddress address = InetAddress.getLocalHost();
server = new ServerSocket(port, 1, address);
}
return server;
}
I have also tried the following alternative:
SocketServer createServer(final int port) throws IOException {
// Create a new socket server
final SocketServer server = new SocketServer();
server.setReuseAddress(true);
try {
// Try to bind to all interfaces
server.bind(new InetSocketAddress(port), 1);
} catch (BindException e) {
// If that fails, try to bind to the primary IP address
final InetAddress address = InetAddress.getLocalHost();
server.bind(new InetSocketAddress(address, port), 1);
}
return server;
}
Both of these alternatives throw a BindException when port is a dynamic port. I have verified that all of the roughly 50 dynamic ports I tested are available according to the results of netstat -an. Is there any way to create a SocketServer for a specific dynamic port?
Although not ideal since it involves registry edits, there is an answer provided on Server Fault.
Windows can be setup to exclude ports from its range of dynamic ports. Simply add the range(s) to exclude to the Multi-String value:
HKLM\System\CurrentControlSet\Services\TCPIP\Parameters\ReservedPorts
So, in my case I have a requirement to use ports 55101-55107, so I added that text to the registry value and restarted the computer. While this solution allows me to use those ports, it is disappointing that I have to edit the registry on any Windows machine where I want to use them. In addition, if I have to add another dynamic port in the future, I will have to re-edit the registry.
We want to capture the data which comes to the system on port say 7777.
public static void main(String[] args) {
try {
final ServerSocket serverSocket = new ServerSocket(7777);
new Thread("Device Listener") {
public void run() {
try {
System.out.println("Listener Running . . .");
Socket socket = null;
while ((socket = serverSocket.accept()) != null) {
System.out.println("| Incoming : "+ socket.toString());
}
} catch (Exception e) {
e.printStackTrace();
}
};
}.start();
} catch (Exception ex) {
ex.printStackTrace();
}
}
We have a device which sends data to the port 7777, which comes with a native windows application. The windows native application is receiving data which comes from that device. We have to receive that data on port 7777 through our java project.
In the above code,
The java server socket is created but no incoming connections are received from the device.
The java server socket is receiving connections from telnet command.
The data format which is used by the device and the other native application may be different, but atleast it has to be connected from java server socket. is it correct?
how to receive the data which is transmitted to port 7777.
EDIT:
Ok, the data is received with UDP socket. it is 68 in length. The device documentation doesn't specify any methods to capture this data, because may be it is designed to work with the specified application. We can't contact the manufacturer also. is there any way (if possible) to know the format of incoming bytes. we have tried network sniffers but we cant understand the format.
If you're receiving from the telnet command, then I suspect you have a network-specific issue.
your device isn't talking to the same ip address / hostname that you're configuring telnet with
you have a routing or firewall issue
is your device possibly using UDP rather than TCP ?
The java server socket is created but no incoming connections are received from the device.
So either there is a firewall in the way or the device isn't trying to connect to that port.
The java server socket is receiving connections from telnet command.
So the Java application is listening to that port.
The data format which is used by the device and the other native application may be different, but at least it has to be connected from java server socket. is it correct?
Yes.
how to receive the data which is transmitted to port 7777.
First you have to accept the connection. On the evidence here the device isn't connecting to port 7777 at all. I suggest some network sniffing is in order to see what it really is doing.
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.
HOST
First, my host is dreamhost. I have root access. The system is a linux system.
SERVER
**UPDATE: It looks like the server uses modsecurity (modsecurity.org). I'll look into it more now, but if anyone has any tips or knows how to work with it, that's where I'm stuck now. **
Second, I wrote a java server that binds to port #### and the listens for connections. I can run this local & connect, but I'm trying to put it up on my server and connect from anywhere. That is the idea behind a server.
private int port;
private ServerSocketChannel ssc;
private Selector selector;
public Server(int port) {
this.port = port;
}
public void run() {
try {
ssc = ServerSocketChannel.open();
selector = Selector.open();
ssc.socket().bind((new InetSocketAddress(port)));
new Thread(new ReadLoop(selector)).start();
new Thread(new AcceptingLoop(ssc, selector)).start();
System.out.println("Bound to port " + port + " and awake:");
} catch (IOException e) {
System.out.println("Server could not start.");
e.printStackTrace();
}
}
I launched this on the server. The program says it successfully bound to the port.
CLIENT
The client is flash, AS3. Here's the code i use to attempt the connect:
var mySocket:XMLSocket = new XMLSocket();
mySocket.connect("http://mydomain.net", ####);
I'm well aware of the sandbox policies. This is something else. I receive this error:
IOERROR [IOErrorEvent type="ioError" bubbles=false cancelable=false eventPhase=2 text="Error #2031: Socket Error. URL: http:--mydomain.net"] (replace -- with //, stackoverflow was reading it as a link)
This error apparently means that Flash never found a server. I would have gotten a security error if it had been the sandbox.
Anyway, how do I tell if ports are open correctly, if they are blocked, etc?
I'm also wondering if this has something to do with it:
http://wiki.dreamhost.com/Mod_security
I unfortunately don't understand a lot of this stuff, but I'm trying to learn.
Try and run your server program on a port that is unlikely to be blocked (e.g. 80, 443). Of course, make sure that nothing else is using the port that you choose.