I'm trying to create a multithreaded broadcasting server. I have one class called ClientHandler
that implements Runnable
, and each instance of this class handles a single connection to a client. My server has a HashSet
called connectedClients
, that stores references to objects of the type Socket
. So I want this ClientHandler
to handle messages to the server, but I want the server to handle messages that goes to the clients, since I can easily just iterate over all of the clients and send one message to each.
I successufully made this server a working echo server. This means that now when I'm reworking it to be able to broadcast messages, I'm sure that everything in the server works except for these two methods:
The
run()
-method of ClientHandler:public void run() { try ( BufferedReader in = new BufferedReader( new InputStreamReader(clientSocket.getInputStream())); ) { String inputLine; while((inputLine = in.readLine()) != null) { chatServer.broadcastMessage(inputLine); } try { in.close(); } catch (IOException e) { System.err.println("Couldn't close input stream"); } } catch(IOException e) { System.err.println("Got an IOException in ClientHandler"); } }
This method just waits for input from the client it's handling, and then sends the input to the server using this method:
broadcastMessage(String message):
public void broadcastMessage (String message) { Iterator<Socket> iterator = this.connectedClients.iterator(); while (iterator.hasNext()) { Socket currentSocket = iterator.next(); try ( PrintWriter out = new PrintWriter(currentSocket.getOutputStream(), true); ) { out.println("Server: " + message); out.close(); } catch(IOException e) { System.err.println("Got an IOException error while reading or writing from/to client"); } } }
This method belongs to the server class, and to be able to use this method I pass along a reference to the instance of the server class when I create a
ClientHandler
inside the server class, like this:new ClientHandler(clientSocket, this)).start();
I can send one message to the server from a client and get a response, but instantly afterwards I get my "Got an IOException in ClientHandler"-error and the program shuts down. Why?
And is this thinking the correct way to implement what I'm trying to implement?
Thanks in advance. Please tell me if I've accidentally left out some important piece of information.
Edit: Here's the stack trace from the IOException:
java.net.SocketException: socket closed
at java.net.SocketInputStream.socketRead0(Native Method)
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 chat.ClientHandler.run(ChatServer.java:120)
at java.lang.Thread.run(Unknown Source)