C graphics
C graphics

Reputation: 7458

How to make sure if a TCP socket is closed on the other end? ( how to read ack signal)

consider the java pseudo code below ( the clisent opens a socket to the server with IP and port 23( telnet):

  static Socket skt = null;   
  skt = new Socket(IP, 23);
  do something
  skt.close()
  ALMOST NO DELAY
  skt = new Socket(IP, 23); // re-opening same socket variable (skt) right after closing it

.. and the exception below sometime happen, because we are trying to re-opening the same socket which not fully closed yet ERROR: java.io.IOException: Connection reset

How can I make sure ( to check) the socket is closed on the other end? in other words, to wait for the acknowledgement from the server, before we go ahead and re-openning that socket in another part of code. - for some reason we have to re-open same socket - also we are not interested in placing delays before re-openning same socket.

In brief : we would like to read the acknowledgment from the server ( the blue line)

enter image description here

Upvotes: 1

Views: 1891

Answers (3)

user207421
user207421

Reputation: 311022

.. and the exception below sometime happen, because we are trying to re-opening the same socket which not fully closed yet ERROR: java.io.IOException: Connection reset

Your analysis is incorrect. That's not the reason. The socket is brand new. The connection is brand new. If you got a 'connection reset', that is because the server software chose to reset the connection. There is nothing you can do about it at this end except investigate why, and at the worst sleep and retry.

It also has nothing to do with running out of local ports as some of the other answers suggest. If that was the problem you would get a BindException.

The fact that your client is sending an RST is very curious though. Are you calling some Socket APIs you haven't shown above?

Upvotes: 0

Mike Clark
Mike Clark

Reputation: 10136

Print the client socket's local port each time after you create it. If you get a new local port for each new client socket, it really is very unlikely to be a problem with "socket reuse" unless there is a bug in the TCP stack. By the way, are you explicitly specifying the local socket number via e.g. Socket.bind or the Socket constructor which accepts a local port? You probably shouldn't. Just let the system pick an ephemeral port.


The problem may be in the server, not in the client. I have no problems when I close and then immediately recreate a client socket to the same host and port. SSCCE made it to 130k connections with no problems before I quit. The loopback interface may be more forgiving than an real NIC, but you could easily modify this code to run across a real network.

public class TestTcpClientServer
{
    public static final int SERVER_PORT = 10111;

    public static void main(String[] args) throws Exception
    {
        Server server = new Server();
        server.start();

        Thread.sleep(500);

        Client client = new Client();
        client.start();

        System.out.println("Press enter to shutdown...");

        System.in.read();

        client.shutdown();
        client.join();
        server.shutdown();
        server.join();

        System.out.println("Done.");
    }

    public static class Client extends Thread
    {
        private volatile boolean shutdown = false;

        public void run()
        {
            try
            {
                int totalClientConnections = 0;

                while (!shutdown)
                {
                    Socket socket = new Socket("localhost", SERVER_PORT);

                    InputStream inputStream = socket.getInputStream();
                    BufferedReader br = new BufferedReader(new InputStreamReader(inputStream));

                    OutputStream outputStream = socket.getOutputStream();
                    BufferedWriter bw = new BufferedWriter(new OutputStreamWriter(outputStream));

                    bw.write("Client saying hello to server");
                    bw.newLine();
                    bw.flush();

                    String readLine = br.readLine();
                    //System.out.println("Client read from server: " + readLine);

                    System.out.println("Socket local port: " + socket.getLocalPort());

                    socket.close();

                    totalClientConnections++;
                    if (totalClientConnections % 10000 == 0)
                    {
                        System.out.println("totalClientConnections=" + totalClientConnections);
                    }

                    Thread.sleep(1000);
                }
            }
            catch (Exception e)
            {
                e.printStackTrace();
            }
        }

        public void shutdown()
        {
            shutdown = true;
        }
    }

    public static class Server extends Thread
    {
        private volatile boolean shutdown = false;
        private ServerSocket serverSocket = null;

        public void run()
        {
            try
            {
                int totalServerConnections = 0;

                serverSocket = new ServerSocket(SERVER_PORT);

                while (!shutdown)
                {
                    Socket socket = serverSocket.accept();

                    InputStream inputStream = socket.getInputStream();
                    BufferedReader br = new BufferedReader(new InputStreamReader(inputStream));

                    OutputStream outputStream = socket.getOutputStream();
                    BufferedWriter bw = new BufferedWriter(new OutputStreamWriter(outputStream));

                    String readLine = br.readLine();
                    //System.out.println("Server read from client: " + readLine);

                    bw.write("Server saying hello to client");
                    bw.newLine();
                    bw.flush();

                    socket.close();

                    totalServerConnections++;
                    if (totalServerConnections % 10000 == 0)
                    {
                        System.out.println("totalServerConnections=" + totalServerConnections);
                    }
                }
            }
            catch (Exception e)
            {
                if (!shutdown)
                {
                    e.printStackTrace();
                }
            }
        }

        public void shutdown()
        {
            shutdown = true;
            try
            {
                serverSocket.close();
            }
            catch (IOException e)
            {
                e.printStackTrace();
            }
        }
    }
}

Upvotes: 1

Erik Ekman
Erik Ekman

Reputation: 2066

A socket is identified by the IP and port in both ends, source and destination. Your second connection should get a different source port, therefore being seen by the server as a separate connection. Make sure that the server is accepting new connections at all times and you should be ok.

Upvotes: 2

Related Questions