Socket closes after sending a message, thus making receiving message impossible

36 views Asked by At

I have a server handler class in my android app that reads and write messages in the Socket, the socket gets passed to it by the ClientController which runs this socket in AsyncTask. connection to the server establishes and I can send a message to it, but once I get the response back the serverhandler cannot read it and logs the Error: Socket closed. I'm not very sure where the problem is, it might be threading issue with android. here is how my ServerHandler class look like:

public class ServerHandler extends Handler implements Runnable {
    private static  ServerHandler instance ;
    private static final Logger logger = LogManager.getLogger(ServerHandler.class);
//    private static final Object lock = new Object();  // For thread-safety
    private final Socket serverSocket;
    private final PrintWriter broadcaster;
    private final ClientController clientController = ClientController.getInstance();


    @Getter
    public enum State {
//some States i need for message handling
    }
    @Getter
    private State expectedState = State.CONNECT_MENU;
    Gson gson = new GsonBuilder()
            .registerTypeAdapter(Object.class, new NewLineAppendingSerializer<>())
            .create();

    public static synchronized ServerHandler getInstance(Socket socket) {
        if (instance == null) {
            instance = new ServerHandler(socket);
        }
        return instance;}
    public ServerHandler(Socket socket) {

        this.serverSocket = socket;
        PrintWriter writer;
        try {
            writer = new PrintWriter(serverSocket.getOutputStream(), false);
        } catch (Exception e) {
            writer = null;
        }
        broadcaster = writer;
}



    @Override
    public void run() {
        new Thread(() ->{
            try {
                BufferedReader reader = new BufferedReader(
                        new InputStreamReader(serverSocket.getInputStream()));
                PrintWriter writer = new PrintWriter(
                        serverSocket.getOutputStream(), false);

                String request, response;
                while (true) {

                    if ((request = reader.readLine()) != null
                            && (response = handle(request)) != null) {
                        logger.info("this is the message from server: " + request);
                        writer.println(response);
                        writer.flush();
                    }
                }
            } catch (JsonSyntaxException | MalformedJsonException e) {
                // Handle MalformedJsonException
                logger.error("The request is not in json format: " + e.getMessage());
            } catch (IOException e) {
                logger.error("Error while trying to read the server message: " + e.getMessage());
            } finally {
                try {
                    serverSocket.close();
                } catch (IOException e) {
                    logger.error("Error while trying to close the connection: " + e.getMessage());
                }
            }
        }
                ).start();
    }
    /**
     * Writes the specified message to the broadcaster
     */
    public void broadcast(String message) {
        new Thread(() -> {try (PrintWriter writer = this.broadcaster) {
            if (writer != null) {
                writer.write(message);
                writer.flush();
            } else {
                logger.error("Error broadcasting message: broadcaster is null");
            }
        } catch (Exception e) {
            logger.error("Error broadcasting message", e);
        }}).start();


    }


    private String handle(String request) {
// handles the messages
}

and here is how the Socket is initiated and passed to ServerHandler:

public class ClientController {

    // some variables
    private ClientController() {
        new SocketInitializationTask().execute();

    }

    private static class SocketInitializationTask extends AsyncTask<Void, Void, Socket> {
        @Override
        protected Socket doInBackground(Void... params) {
            try {
                String serverAddress = "192.168.0.208";
                int serverPort = 8082;
                return new Socket(serverAddress, serverPort);
            } catch (IOException e) {
                logger.error("Failed connection");
                // Handle exception
                return null;
            }
        }

        @Override
        protected void onPostExecute(Socket socket) {
            if (socket != null) {

                // Set the serverHandler in the ClientController
                instance.serverHandler = new ServerHandler(socket);
                instance.serverHandler.run();

                


            }
        }
    }

and from this class i can send messages using the Broadcast method in serverhandler.

first I ran everything on the main thread but ofc Android didn't allow it so I got suggested to use AsyncTask for socket initialization. Now I do have connection to the server and I can send messages to it, but after sending the first message the socket closes, making the serverhandler not able to read messages. And from the server side I tested if it was the server that closes the socket but it wasn't.

I need the socket to stay open all the time, so I can read messages from the Server.

0

There are 0 answers