zeromq / jeromq

Pure Java ZeroMQ
Mozilla Public License 2.0
2.36k stars 483 forks source link

Socket closed but sends SYN_SENT after a few seconds #993

Open ttcds opened 1 month ago

ttcds commented 1 month ago

After closing a ZMQ.Socket like below (simplified code) a few seconds later a SYN_SENT is send which causes an underlying tcp socket to connect again. And when starting a new thread with a new ZMQ.Socket there are 2 tcp sockets open to the endpoint while the first one should have never reconnected again by itself.

Code

public class Main
{
    static ZContext context = new ZContext();

    public static void main(String[] args) throws InterruptedException
    {
        var runner = new RemoteDealer.Runner();
        var runnerThread = new Thread(runner);
        runnerThread.start();

        Thread.sleep(5000);

        runnerThread.interrupt();

        runner = new Runner.Runner();
        runnerThread = new Thread(runner);
        runnerThread.start();
        Thread.sleep(6000);
    }

    static class Runner implements Runnable
    {
        ZMQ.Socket socket;

        @Override
        public void run()
        {
            String endpoint = "tcp://" + remoteIp + ":60000";

            try
            {
                socket = context.createSocket(SocketType.DEALER);
                socket.setTCPKeepAlive(1);
                socket.setTCPKeepAliveCount(1);
                socket.setTCPKeepAliveIdle(8);
                socket.setTCPKeepAliveInterval(5);
                socket.setLinger(0);
                socket.setHandshakeIvl(0);
                socket.setReconnectIVL(30000);
                socket.setSendTimeOut(5000);
                socket.setReceiveTimeOut(5000);
                socket.connect(endpoint);

                ZMQ.Poller poller = context.createPoller(6);
                poller.register(socket, ZMQ.Poller.POLLIN);

                while (!Thread.currentThread().isInterrupted())
                {
                    poller.poll();
                    try
                    {
                        if (poller.pollin(0))
                        {
                            ...
                        }
                    } catch (Exception ex)
                    {
                        ex.printStackTrace();
                    }
                }
            }
            catch (Exception ex)
            {
                ex.printStackTrace();
            }
            finally
            {
                socket.disconnect(endpoint);
                socket.close();
            }
        }
    }
}
public static void main(String[] args)
{
    var router = "tcp://*:" + 60000;

    var context = new ZContext();

    ZMQ.Socket routerSocket = context.createSocket(SocketType.ROUTER);
    routerSocket.setTCPKeepAlive(1);
    routerSocket.setTCPKeepAliveCount(1);
    routerSocket.setTCPKeepAliveIdle(8);
    routerSocket.setTCPKeepAliveInterval(5);
    routerSocket.setLinger(0);
    routerSocket.setHandshakeIvl(0);
    routerSocket.setSendTimeOut(5000);
    routerSocket.setReceiveTimeOut(5000);
    routerSocket.bind(router);

    var poller = context.createPoller(6);
    poller.register(routerSocket, ZMQ.Poller.POLLIN);

    var runnerThread = new Thread(() -> {
        try
        {
            while (!Thread.currentThread().isInterrupted())
            {
                poller.poll();

                if (poller.pollin(0))
                {
                    ...
                }
            }
        } catch (Exception ex)
        {
            ex.printStackTrace();
        } finally
        {
            routerSocket.close();
        }
    });

    runnerThread.start();
    Thread.sleep(1000000);
}

After a few disconnects and reconnects the output of netstat looks like this:

tcp        0      0 src:35476    dst:60000 ESTABLISHED
tcp        0      0 src:35480    dst:60000 ESTABLISHED
tcp        0      0 src:35482    dst:60000 ESTABLISHED
tcp        0      0 src:35484    dst:60000 ESTABLISHED
trevorbernard commented 1 month ago

@ttcds Thank you for the test case but we'll need more information about the where the server and client is running on. What version of Linux and the kernel are you running?

ttcds commented 1 month ago

@trevorbernard I am using a Yocto build (dunfell) and using kernel 5.4.147.

The situation is as follows:

trevorbernard commented 1 month ago

What version of the Java SDK?

ttcds commented 1 month ago

Openjdk 17.0.10

trevorbernard commented 4 weeks ago

@ttcds is the issue that there are extraneous SYN packets sent or that the ROUTER maintains an established connection with a closed socket?