Reputation: 11
I am trying to test my chat client application by creating a socket and connecting it to the server, sending a message and closing the socket (via the server's close method). However, it seems that when I close the socket the client thread still awaits for client input. However, I have put if clause to stop it from waiting. Here is my test:
@Test
public void testMessagesReceived() throws IOException
{
ServerSocket s = server.getSocket();
System.out.println(s);
mysocket = new Socket("127.0.0.1", 3000);
final PrintWriter stream = new PrintWriter(mysocket.getOutputStream(), true);
stream.println("Default room");
}
@AfterSuite
public void stopServer() {
try {
Thread.sleep(3000);
} catch (InterruptedException e) {
e.printStackTrace();
}
server.stop();
}
However, when the server.stop()
executes and closes the socket I get an exception in the client thread which is alive and uses this socket, here:
public void acceptFromConsole() throws IOException {
if (!socket.isClosed()) {
final BufferedReader fromClient = new BufferedReader(new InputStreamReader(socket.getInputStream()));
String message;
while ((message = fromClient.readLine()) != null) { // Exception here
if (message.contains(TelnetUtilities.Quit.toString())) {
room.removeClient(id);
break;
}
}
Here is the full stacktrace:
java.net.SocketException: Socket closed
at java.net.SocketInputStream.socketRead0(Native Method)
at java.net.SocketInputStream.socketRead(Unknown Source)
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.egt.chat.server.ClientContainer.acceptFromConsole(ClientContainer.java:40)
at com.egt.chat.server.ClientContainerRunnable.run(ClientContainerRunnable.java:28)
at java.util.concurrent.ThreadPoolExecutor.runWorker(Unknown Source)
at java.util.concurrent.ThreadPoolExecutor$Worker.run(Unknown Source)
at java.lang.Thread.run(Unknown Source)
It seems to me that in one thread I close the socket ,however the client thread doesn't see the change on the socket and that check if(!socket.isClosed()) returns true and the flow of execution continues and while I try to read it of course throws exception that I am trying to read from a closed socket ,is there a way to overcome this?
Upvotes: 0
Views: 331
Reputation: 42774
Your code is working as it should be. When you forcefully disconnect the socket your code is the while loop:
while ((message = fromClient.readLine()) != null) { // Exception here
if (message.contains(TelnetUtilities.Quit.toString())) {
room.removeClient(id);
break;
}
readLine()
is waiting for incoming data. If you would not close the connection it would wait forever for new data. Then you close the connection and readLine()
(or better the underlaying socketRead
method) now recognizes that it can't read data from a closed socket and raises the exception.
Therefore this exception is an expected exception at this point. Catch it and be happy.
I would do it this way: Add a boolean variable like stopServerCalled
which is by default false
and is set to true
when stopServer()
is called.
try {
while ((message = fromClient.readLine()) != null) { // Exception here
if (message.contains(TelnetUtilities.Quit.toString())) {
room.removeClient(id);
break;
}
} catch (SocketException e) {
// check if this is an expected exception and if yes ignore it
if (!stopServerCalled)
throw e;
}
Upvotes: 1