Home > Mobile >  How to detect Java socket disconnection from client side?
How to detect Java socket disconnection from client side?

Time:05-31

I am developing a simple Java class with a thread that creates a Client socket that connects to a server. This thread retrieves bytes via a BlockingQueue then sends them to the server, then retrieves bytes again, etc.

My problem is that I don't know on which condition the while structure should loop. I would actually like to be able to retrieve a "disconnect" from the server without the server having to send data indicating a disconnect.

How can I solve this?

Here is my code:

public class ClientThread extends Thread {
    private static final String TAG = "ClientThread";

    private Socket socket = null;
    private OutputStream out = null;
    private BlockingQueue<Message> queue = null;

    private static final int SERVERPORT = 8080;
    private static final String SERVER_IP = "localhost";

    public ClientThread(BlockingQueue<Message> queue) {
        this.queue = queue;
    }

    @Override
    public void run() {
        try {
            InetAddress serverAddr = InetAddress.getByName(SERVER_IP);

            //send a request to connect to the server is listening on machine 'localhost', port 8080
            socket = new Socket(serverAddr, SERVERPORT);

            //create output stream to send data to the server
            out = socket.getOutputStream();

            while (/* a condition */) {
                //Do some work on socket
            }
        } catch (UnknownHostException e1) {
            e1.printStackTrace();
        } catch (IOException e1) {
            e1.printStackTrace();
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
    }

    @Override
    protected void finalize() throws Throwable {
        try {
            socket.close();
            out.close();
        } catch (IOException e) {
            e.printStackTrace();
        }
    }
}

CodePudding user response:

I wrote a simple Client-Server communication to showcase how you can solve that:

package stackoverflow.multithreadingfiles.servlets;

import java.io.IOException;
import java.io.InputStream;
import java.net.ServerSocket;
import java.net.Socket;

public class TestSocket {

    static public final int PORT = 12345;

    public static void main(final String[] args) {
        runServerThread();
        sleep(2000);
        runClientThread();
    }



    private static void sleep(final int pMS) {
        try {
            Thread.sleep(pMS);
        } catch (final InterruptedException e) { /* */ }
    }

    private static void runServerThread() {
        final Thread t = new Thread(() -> runServer());
        t.setName("Server Thread");
        t.start();
    }
    private static void runClientThread() {
        final Thread t = new Thread(() -> runClient());
        t.setName("Client Thread");
        t.setDaemon(true);
        t.start();
    }

    private static void runServer() {
        System.out.println("Server Thread starting");
        try (final ServerSocket ss = new ServerSocket(PORT);) {
            while (true) {
                System.out.println("Server Thread waiting for new connection...");
                try (final Socket socket = ss.accept();) {
                    System.out.println("Server Thread connected...");
                    while (!socket.isClosed()) {
                        socket.getOutputStream().write((int) (Math.random() * 100));
                        sleep((int) (Math.random() * 1000));
                        if (Math.random() < 0.1) {
                            System.out.println("Server Thread disconnecting...");
                            //                          socket.close(); you can commemt that in or out, will not have any effect
                            break;
                        }
                    }
                } // auto-closes Socket here
            }
        } catch (final IOException e) {
            e.printStackTrace();
        } finally {
            System.out.println("Server Thread ended.");
        }
    }
    private static void runClient() {
        System.out.println("Client Thread starting");
        try (Socket s = new Socket("localhost", PORT);
                InputStream sis = s.getInputStream()) {
            final byte[] buffer = new byte[256];
            while (!s.isClosed()) { // s.isClosed() will actually NOT indicate if Server closed the Socket, so you can just write while(true)
                final int bytesRead = sis.read(buffer);

                System.out.print("Client received "   bytesRead   " bytes: ");
                for (int i = 0; i < bytesRead; i  ) {
                    System.out.print("\t"   buffer[i]);
                }

                System.out.println();
                if (bytesRead < 0) { // actually value will be -1 if socket is closed. Same if you read a single byte with sis.read();
                    // this check usually comes directly after reading from the socket, but I wanted to showcase the -1 data length you'll get
                    System.out.println("Client noticed that connection was closed.");
                    break;
                }

            }

        } catch (final Exception e) {
            e.printStackTrace();
        } finally {
            System.out.println("Client Thread ended.");
        }
    }



}

CodePudding user response:

Try using Socket#isClosed(), or a global variable, that is set when the client disconnects.

  • Related