【发布时间】:2018-02-24 12:37:52
【问题描述】:
所以我为我的树莓派编写了一个客户端-服务器应用程序——为了处理服务器上的多个客户端,我总是为每个客户端套接字打开一个新的“ClientMessageListener”线程。
我试图创建一个销毁链,当我希望 ServerSocket 关闭时调用它。它遍历每个线程并调用 ClientMessageListener 的销毁方法,该方法应该关闭连接资源,然后关闭套接字本身。
我的客户端处理程序如下所示:
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();
}
}
}
}
一切正常,当我在 destroy() 方法中关闭资源时,我希望 this.in.readLine() 调用抛出 IOException,因此线程刚刚结束。但是在调用 this.in.close() 时,destroy-method 会阻塞,并且绝对不会抛出异常。
即使 Thread.getCurrentThread.interrupt() 也不起作用,我不知道为什么。是否有一个干净的解决方案来关闭资源并结束 run() 方法?
【问题讨论】:
-
为什么不直接关闭
Socket? -
很难说。你没有提供你的真实代码,只有“类似这样的东西”,所以谁知道。但是关闭
Socket肯定会毁掉你的听众。 -
那里有很多不必要的代码。进行持续的空检查,就像您不知道您的对象处于什么状态一样。外部流/读取器也会关闭它们的内部流,因此您只需要关闭最外面的流。您可以用
if(socket != null) { socket.close(); socket = null; }替换整个destroy()方法。 -
不,它们不相关。你刚刚写了很多无意义的安全代码,因为你不明白什么会出错。至少您可以免受永远不会发生的情况的影响,但这只会导致大量不必要的代码。此外,如果资源没有正确初始化,你甚至不应该调用
destroy()。 -
您还应该避免使用
booleans来指示方法成功。让异常冒泡并在初始化完成的地方处理它们。
标签: java multithreading sockets server client