SocketServer Always Throws BindException for Dynamic Ports - java

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.

Related

How to know ip address with java.net InetAddress or other API

I have UDP server to listen messages, and I need to bind to device IP address. Other devices send messages on the UDP server. I use next:
InetAddress address = InetAddress.getLocalHost(); // gives 127.0.1.1 (1)
address = InetAddress.getLoopbackAddress(); // 127.0.0.1 (2)
address = InetAddress.getByName("123.45.67.89"); // the same (3)
address = InetAddress.getByName("localhost"); // (4)
I run my code on different environments and see next:
On my local machine with win10 .getByName("localhost") works and .getLocalHost() not worked. Also other devices (emulators) send messages on "localhost".
On other remote PC with Win7 and some IP I'm using (1) and it works. Physical devices send messages on server IP and it process them. Also, I'm using bridge to allow devices communicate with each other, i.e. devices placed in different networks (I don't understand this configuration, it is not my).
On this remote PC but in Linux I can set address only manually, i.e. variant (3). But I need specify it automatically.
I can't get the correct server address by any method. How I can get device address? Maybe there are some another methods or API?
UPD: I'm using netty udp server with standard configuration:
#Override
public void run() {
final NioEventLoopGroup group = new NioEventLoopGroup();
try {
log.info("Started listening logs ...");
final Bootstrap bootstrap = new Bootstrap();
bootstrap.group(group).channel(NioDatagramChannel.class)
.option(ChannelOption.SO_BROADCAST, true)
.handler(new ChannelInitializer<NioDatagramChannel>() {
#Override
public void initChannel(final NioDatagramChannel nioDatagramChannel) {
ChannelPipeline channelPipeline = nioDatagramChannel.pipeline();
channelPipeline.addLast(encryptedPacketHandlerChain);
}
});
// Bind and start to accept incoming connections.
InetAddress address = InetAddress.getLocalHost();
System.out.println("InetAddress..getLocalHost() == " + address.getHostAddress());
address = InetAddress.getLoopbackAddress();
System.out.println("InetAddress.getLoopbackAddress == " + address.getHostAddress());
address = InetAddress.getByName(ip);
System.out.println("InetAddress.getByName " + ip + " == " + address.getHostAddress());
bootstrap.bind(address, LOG_PORT).sync().channel().closeFuture().await();
} catch (Exception e) {......
A host may have several network interfaces connected to different networks, and the bind address tells the system which interface you want to listen on. This is typically configured by the user of your application (system administrator) because the networks have different purposes (for example, data plane vs control plan: one network used by system and network admins to control the machine, another network used for production traffic)
If you don't know which interface you should listen on, you can listen on all local interfaces. You do that by binding to the special 0.0.0.0 or :: IP address.
One way you can create the 0.0.0.0 address by first creating a SocketAddress with the InetSocketAddress(int port) constructor, and then retrieving the address from it:
InetAddress anyAddress = new InetSocketAddress(LOG_PORT).getAddress();
Another way is creating the the address directly:
InetAddress anyAddress = InetAddress.getByAddress(new byte[4]);

Setting source port on udp socket

We've developed a Java application that sends several UDP datagrams to the very same destination IP address. Obviously the destination port is always the same one, but we can't seem to be able to set the source port to remain the same on each datagram.
If the data package we send is bigger than MTU the package is properly splitted over the same source port, but once we send a new data package the source port changes, generating a new firewall session (which network admin has warned us to be very bad due to the amount of sessions the application is generating).
Right now we're sending the packages with the following statement:
We've tried several approaches and the result is always the same, we can't seem to be able to set the source port to a fixed value.
Edit- pasting actual code:
private boolean sendImage(byte[] imageData, InetAddress address,
int port) throws UnknownHostException, SocketException {
boolean ret = false;
DatagramSocket socket = null;
try {
socket = new DatagramSocket();
DatagramPacket dp = new DatagramPacket(imageData, imageData.length, address, PUERTO_UDP);
socket.send(dp);
ret = true;
} catch (IOException e) {
Main.lanzarExcepcion(e);
ret = false;
} finally {
if (socket != null) {
socket.close();
}
}
return ret;
}
Thanks for your time!
I think your issue is that you are closing the actual DatagramSocket instead of reusing the same , and simply call socket.send(DatagramPacket). If you cant keep the client socket open , then you could even define the clients port like : DatagramSocket clientSocket = new DatagramSocket(9743); so each time you are calling a new clientSocket , it will get the same port or it will throw a java.net.BindException: Address already in use: Cannot bind
This will not solve the network sessions issue, because you are opening a new UDP Socket. Also i suspect that your network admin , sees the previous sessions , because you are not closing the UDP Sockets at all , but simply spawning them
As mentioned by #AntJavaDev
The solution was to:
1.- keep the DatagramSocket open
2.- pass src port in the arguments
3.- reusing the unclosed DatagramSocket for every new data packet to the same destination!
Thanks all!
The source port is an ephemeral port, generated for you by the underlying networking implementation. There is no reason to set it to a particular port number.

Prevent an app from binding to a socket that is already bound

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?

Netty is giving me a wrong port using TCP

I'm using Netty with Java trying to configure a TCP client. Everything is working so far, except that I'm connecting on port 1050 but when I call messageEvent.getRemoteAddress() on messageReceived() method of the handler, I'm getting the port 1500. I changed the port to 1049 but I'm still receiving 1500. This is Netty's problem or can it be the server's problem?
My hardware setup here is: this netty client running on a Java server, and several access control equipments spread through the area here. The equipments act as tcp servers and the netty as the client, that process everything the server sends and just reply to them.
The tcp server initialization is this:
private ChannelFactory fabrica;
private ServerBootstrap bootstrap;
public void iniciarServidorTCP() {
fabrica = new NioServerSocketChannelFactory(
Executors.newCachedThreadPool(),
Executors.newCachedThreadPool());
bootstrap = new ServerBootstrap(fabrica);
bootstrap.setPipelineFactory(new ChannelPipelineFactory() {
#Override
public ChannelPipeline getPipeline() throws Exception {
ChannelPipeline pipeline = Channels.pipeline();
pipeline.addLast("decoderDeMensagem", new MensagemDecoderTCP());
pipeline.addLast("handlerGerente", new GerenteTCP());
pipeline.addLast("encoder de mensagem", new MensagemEncoderTCP());
return pipeline;
}
});
bootstrap.setOption("child.tcpNoDelay", true);
bootstrap.setOption("child.reuseAddress", true);
bootstrap.bind(new InetSocketAddress(1050));
}
Any idea why I'm getting 1500 instead of 1050? Could it be a problem with the equipment?
Every TCP connection has a source port and a destination port. When you connect to a server, the server sees the destination port as its well-known address. The client picks the source port. On either end, getting the "remote address" gets the other side's address. So when you call get remote address on the server, you get the client's address, not the server's.
Imagine you have a server with one IP address and one well-known port. Now, say you have a client machine with one IP address. If it make's four connections to the server, how can either end tell those connections apart? The answer is that the client port is different.

How to establish homebrew server connection

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.

Categories

Resources