Reputation: 41
So I wrote a Client-Server-application for my raspberry pis - to handle multiple clients on the server I always open a new "ClientMessageListener"-thread for every client-socket.
I tried to create a destroy-chain which is called when I want the ServerSocket to shutdown. It iterates through every thread and calls the destroy-method of the ClientMessageListener which should close the connection-resources and then the socket itself.
My client-handlers look like this:
package com.imnos.piserver.server.serversocket.client;
import com.imnos.piserver.server.serversocket.ServerRequestController;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.PrintWriter;
import java.net.Socket;
/**
* @author simon
*/
public class ClientMessageListener implements Runnable {
private static final ServerRequestController SRC
= ServerRequestController.getInstance();
private Socket clientSocket = null;
private PrintWriter out = null;
private InputStreamReader inputStream = null;
private BufferedReader in = null;
ClientMessageListener(final Socket clientSocket) {
this.clientSocket = clientSocket;
this.initDataStream();
}
/**
* @return
*/
synchronized boolean destroyClientMessageListener() {
if (this.clientSocket == null) {
return false;
}
if (this.in != null) {
try {
this.in.close(); // Method stucks here
} catch (IOException ignore) {
ignore.printStackTrace();
} finally {
this.in = null;
}
}
if (this.inputStream != null) {
try {
this.inputStream.close();
} catch (IOException ignore) {
ignore.printStackTrace();
} finally {
this.inputStream = null;
}
}
if (this.out != null) {
this.out.close();
this.out = null;
}
return true;
}
/**
* @return
*/
private synchronized boolean initDataStream() {
if (this.clientSocket == null) {
return false;
}
if (this.clientSocket.isClosed()) {
return false;
}
try {
this.out = new PrintWriter(
this.clientSocket.getOutputStream(), true);
this.inputStream = new InputStreamReader(
this.clientSocket.getInputStream());
this.in = new BufferedReader(this.inputStream);
return true;
} catch (IOException ex) {
this.destroyClientMessageListener();
ex.printStackTrace();
}
return false;
}
/**
*
*/
@Override
public void run() {
if (in != null) {
String strInput;
try {
while ((strInput = this.in.readLine()) != null) {
final boolean success
= SRC.handleIncoming(
this.clientSocket, strInput);
}
} catch (IOException ignore) {
ignore.printStackTrace();
}
}
}
}
Everything works fine and I expected the this.in.readLine()-call to throw an IOException when I close the resource in the destroy()-method so the thread just ends. But instead the destroy-method blocks when calling this.in.close() and absolutely no Exception is thrown.
Even Thread.getCurrentThread.interrupt() does not work and I have no idea why. Is there a clean solution to close the resources and end the run()-method?
Upvotes: 1
Views: 640
Reputation: 310911
Shutdown the socket for input. That will cause readLine()
to return null, which will cause the thread that is reading the socket to close it and exit.
Upvotes: 1