Netty 4.0.17 basic server grabs a bunch of TCP ports on loopback on windows

Issue

I’m running an echo server on windows 7 ultimate using jdk 1.7.0 (u51) 64bit.

java version "1.7.0_51"
Java(TM) SE Runtime Environment (build 1.7.0_51-b13)
Java HotSpot(TM) 64-Bit Server VM (build 24.51-b03, mixed mode)

On Linux / Mac, netstat shows that this process only grabs the specified port (9809 for the example for listening). However on windows it also grabs a bunch of other TCP ports on loopback (127.0.0.1).

EDIT: The behavior is the same for netty versions 4.0.17.Final and the just released 4.0.18.Final

Netstat listing for one run (the PID was 4956):

PS C:\Users\xxxx> netstat -ano | select-string 4956

  TCP    0.0.0.0:9809           0.0.0.0:0              LISTENING       4956
  TCP    127.0.0.1:50682        127.0.0.1:50683        ESTABLISHED     4956
  TCP    127.0.0.1:50683        127.0.0.1:50682        ESTABLISHED     4956
  TCP    127.0.0.1:50684        127.0.0.1:50685        ESTABLISHED     4956
  TCP    127.0.0.1:50685        127.0.0.1:50684        ESTABLISHED     4956
  TCP    127.0.0.1:50686        127.0.0.1:50687        ESTABLISHED     4956
  TCP    127.0.0.1:50687        127.0.0.1:50686        ESTABLISHED     4956
  TCP    127.0.0.1:50688        127.0.0.1:50689        ESTABLISHED     4956
  TCP    127.0.0.1:50689        127.0.0.1:50688        ESTABLISHED     4956
  TCP    127.0.0.1:50690        127.0.0.1:50691        ESTABLISHED     4956
  TCP    127.0.0.1:50691        127.0.0.1:50690        ESTABLISHED     4956
  TCP    127.0.0.1:50692        127.0.0.1:50693        ESTABLISHED     4956
  TCP    127.0.0.1:50693        127.0.0.1:50692        ESTABLISHED     4956
  TCP    127.0.0.1:50694        127.0.0.1:50695        ESTABLISHED     4956
  TCP    127.0.0.1:50695        127.0.0.1:50694        ESTABLISHED     4956
  TCP    127.0.0.1:50696        127.0.0.1:50697        ESTABLISHED     4956
  TCP    127.0.0.1:50697        127.0.0.1:50696        ESTABLISHED     4956
  TCP    127.0.0.1:50698        127.0.0.1:50699        ESTABLISHED     4956
  TCP    127.0.0.1:50699        127.0.0.1:50698        ESTABLISHED     4956
  TCP    127.0.0.1:50700        127.0.0.1:50701        ESTABLISHED     4956
  TCP    127.0.0.1:50701        127.0.0.1:50700        ESTABLISHED     4956
  TCP    127.0.0.1:50702        127.0.0.1:50703        ESTABLISHED     4956
  TCP    127.0.0.1:50703        127.0.0.1:50702        ESTABLISHED     4956
  TCP    127.0.0.1:50704        127.0.0.1:50705        ESTABLISHED     4956
  TCP    127.0.0.1:50705        127.0.0.1:50704        ESTABLISHED     4956
  TCP    [::]:9809              [::]:0                 LISTENING       4956

These don’t show up on Linux/Mac, only on Windows. I’m assuming this is some sort of IPC mechanism on windows (per worker thread perhaps), but wished to ask if anyone can authoritatively clarify this for me. The issue is since netty / java grabs these local ports running any other apps trying to bind to these ports (mostly dev servers, debuggers allocating random high ports) fail with a permission denied type error message. I mostly work on linux/mac, so wondering if I missed some obvious redmondism 🙂

The echo server code is given below: ( I boiled it down to a basic server to test)

package test;

import io.netty.bootstrap.ServerBootstrap;
import io.netty.buffer.ByteBuf;
import io.netty.channel.Channel;
import io.netty.channel.ChannelHandlerContext;
import io.netty.channel.ChannelInitializer;
import io.netty.channel.SimpleChannelInboundHandler;
import io.netty.channel.nio.NioEventLoopGroup;
import io.netty.channel.socket.SocketChannel;
import io.netty.channel.socket.nio.NioServerSocketChannel;

public class TestServer extends ChannelInitializer<SocketChannel>{
    private int port = 9809;
    public TestServer(int port) {
        this.port = port;
    }
    public void run() throws Exception {
        NioEventLoopGroup pool = new NioEventLoopGroup();
        try {
            ServerBootstrap bootstrap = new ServerBootstrap();
            Channel c = bootstrap.group(pool).channel(NioServerSocketChannel.class).childHandler(this).bind(port).sync().channel();
            c.closeFuture().sync();
        } finally {
            pool.shutdownGracefully();
        }
    }
    /**
     * @param args
     */
    public static void main(String[] args) throws Exception {
        int port = 9809;
        TestServer server = new TestServer(port);
        server.run();

    }
    @Override
    protected void initChannel(SocketChannel channel) throws Exception {
        channel.pipeline().addLast("handler", new Handler());
    }

    private class Handler extends SimpleChannelInboundHandler {

        @Override
        protected void channelRead0(ChannelHandlerContext ctx, Object obj)
                throws Exception {
            ByteBuf buf = (ByteBuf)obj;
            ctx.writeAndFlush(buf.retain());
        }

    }

}

Solution

I think I remember this is just how java NIO works on Windows so there is nothing we can do about it in Netty.

On Windows, the epoll system call does not exist. Thus, in order to get notifications from the network, this is the workaround that has been implemented.

In order to reproduce, just open a Selector:

Selector selector = Selector.open();
Thread.sleep(Integer.MAX_VALUE);

And you will observe the cross referenced TCP connections on windows:

  TCP    127.0.0.1:51431        127.0.0.1:51432        ESTABLISHED
 [javaw.exe]
  TCP    127.0.0.1:51432        127.0.0.1:51431        ESTABLISHED
 [javaw.exe]

Normally, those connections should close as soon as you close the Selector:

selector.close();

Answered By – Norman Maurer

This Answer collected from stackoverflow, is licensed under cc by-sa 2.5 , cc by-sa 3.0 and cc by-sa 4.0

Leave a Reply

(*) Required, Your email will not be published