0

I try to make basic Java Chatting Application with java socket APIs. But when the client is terminated, it throws the following Exception,

java.net.SocketException: Socket closed

My code

Server

package com.aaa.server;

import java.io.BufferedReader;
import java.io.InputStreamReader;
import java.io.OutputStreamWriter;
import java.io.PrintWriter;
import java.net.ServerSocket;
import java.net.Socket;
import java.util.Collection;
import java.util.Collections;
import java.util.HashMap;
import java.util.Iterator;
import java.util.Map;

public class JavaChatServer {

    final static int Port = 10001; 

    public static void main(String[] args) {
        // TODO Auto-generated method stub
        ServerSocket serverSocket = null;
        Map<String, PrintWriter> clientMap = null;

        try {
            serverSocket = new ServerSocket(Port);
            clientMap = new HashMap<String, PrintWriter>();
            Collections.synchronizedMap(clientMap);

            while(true) {
                System.out.println("Waiting Connection ....");
                Socket socket = serverSocket.accept();

                ServerThread thread = new ServerThread(socket, clientMap);
                thread.start();
            }
        } catch (Exception e) {
            e.printStackTrace();
        } finally {
            try {
                if(!serverSocket.isClosed()) {
                    serverSocket.close();
                }
            } catch (Exception e1) {
                e1.printStackTrace();
            }
        }
    }

}

class ServerThread extends Thread {
    private Socket socket = null;
    private BufferedReader br = null;

    private Map<String, PrintWriter> clientMap;
    private String id;

    public ServerThread(Socket socket, Map<String, PrintWriter> clientMap) {
        this.socket = socket;
        this.clientMap = clientMap;
    }

    @Override
    public void run() {
        try {
            br = new BufferedReader(new InputStreamReader(socket.getInputStream()));
            PrintWriter pw = new PrintWriter(new OutputStreamWriter(socket.getOutputStream()));

            id = br.readLine();
            broadcast(id + " is connected");
            System.out.println("Connected User Id : " + id);
            clientMap.put(id, pw);

            String msg = "";

            while(true) {
                msg = br.readLine();

                if(msg.equals("/exit")) {
                    break;
                }

                broadcast(id + " : " + msg);
            }
        } catch (Exception e) {
            e.printStackTrace();
        } finally {
            try {
                clientMap.remove(id);
                broadcast(id + " is disconnected!!");

                if (br != null)
                    br.close();
                if(socket != null)
                    socket.close();
            } catch (Exception e1) {
                e1.printStackTrace();
            }
        }
    }

    private void broadcast(String msg) throws Exception{
        Collection<PrintWriter> collection = clientMap.values();
        Iterator<PrintWriter> iterator = collection.iterator();

        while(iterator.hasNext()) {
            PrintWriter pw = iterator.next();
            pw.println(msg);
            pw.flush();
        }
    }
}

Client

package com.aaa.client;

import java.io.BufferedReader;
import java.io.InputStreamReader;
import java.io.OutputStreamWriter;
import java.io.PrintWriter;
import java.net.Socket;
import java.util.Scanner;

public class JavaChatClient {

    final static int Port = 10001;

    public static void main(String[] args) {
        // TODO Auto-generated method stub
        Socket socket = null;
        PrintWriter pw = null;

        Scanner keyboard = new Scanner(System.in);
        String id = "";

        try {
            socket = new Socket("localhost", Port);

            pw = new PrintWriter(new OutputStreamWriter(socket.getOutputStream()));
            System.out.print("Welcome to Chat Room. Pls, type your ID : ");
            id = keyboard.nextLine();
            pw.println(id);
            pw.flush();

            ClientInputThread inputThread = new ClientInputThread(socket);
            inputThread.start();

            String msg = "";
            while (!msg.toLowerCase().equals("/exit")) {
                msg = keyboard.nextLine();

                if(!msg.trim().equals("")) {
                    pw.println(msg);
                    pw.flush();
                }
            }
        } catch (Exception e) {
            e.printStackTrace();
        } finally {
            try {
                if (keyboard != null)
                    keyboard.close();
                if (pw != null)
                    pw.close();
                if(socket != null)
                    socket.close();
            } catch (Exception e) {
                e.printStackTrace();
            }
        }
    }

}

class ClientInputThread extends Thread {
    private Socket socket = null;

    public ClientInputThread (Socket socket) {
        this.socket = socket;
    }

    @Override
    public void run() {
        BufferedReader br = null;

        try {
            br = new BufferedReader(new InputStreamReader(socket.getInputStream()));
            String msg = "";

            while(true) {
                if(socket.isClosed())
                    break;

                msg = br.readLine(); // This line throws SocketException
                System.out.println(msg);
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
    }
}

When the generated clients is terminated with "/exit" message, the BufferedReader.readLine() line throws the exception like below

java.net.SocketException: Socket closed
        at java.net.SocketInputStream.read(Unknown Source)
        at java.net.SocketInputStream.read(Unknown Source)
        at sun.nio.cs.StreamDecoder.readBytes(Unknown Source)
        at sun.nio.cs.StreamDecoder.implRead(Unknown Source)
        at sun.nio.cs.StreamDecoder.read(Unknown Source)
        at java.io.InputStreamReader.read(Unknown Source)
        at java.io.BufferedReader.fill(Unknown Source)
        at java.io.BufferedReader.readLine(Unknown Source)
        at java.io.BufferedReader.readLine(Unknown Source)
        at com.aaa.client.ClientInputThread.run(JavaChatClient.java:80)

I think the BufferedReader stream still try to read line message even though the socket is already closed.

But I hava no idea when and how to close the BufferedReader Stream and Socket connection when the clients is terminated.

I am totally stuck on this part. Any ideas?

2
  • 1
    That sound about right. What else did you expect to happen? As for handling it, why not catch it explicitly, and clean up after yourself (or let the finally handler run)? Commented Aug 4, 2018 at 6:12
  • Thank you for reply. I try to do my efforts to erase this exception when the client terminated. I want to know how to close the socket of client simultaneously when the server connection is terminated. The problem is the stream of client is still alive even if the socket of server side is closed. Best regards. Commented Aug 4, 2018 at 6:37

1 Answer 1

0

This is because when you are calling readLine(), socket is closed. You can first check the msg, if the msg is \exit, then first stop inputThread (use a flag or something else), then send \exit to the server. In a short, check /exit -> stop inputThread -> send /exit to server.

String msg = "";
while (!msg.toLowerCase().equals("/exit")) {
    msg = keyboard.nextLine();

    if (msg.toLowerCase().equals("/exit")) {
        // stop inputThread.
        // make sure inputThread is stopped.
    }

    if (!msg.trim().equals("")) {
        pw.println(msg);
        pw.flush();
    }
}
Sign up to request clarification or add additional context in comments.

1 Comment

I think you can show the code to help Joseph (and me) understand your answer

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.