【发布时间】:2013-07-21 18:41:34
【问题描述】:
我正在用 java 创建一个到服务器的套接字,在连接套接字后,它会创建一个新线程,该线程可以访问套接字输入和输出流,然后该线程会在输入行进入时阻塞并处理它们。
我了解 BufferedReader 上的 readln 方法将在输入流结束时返回 null。这并不一定意味着套接字已关闭,不是吗?这是什么意思?所以我想在套接字上运行close 方法来很好地关闭它。
我还了解到readln 方法可以抛出 IOException,并且如果当前阻塞,则在套接字上调用 close 方法之后抛出该异常。这还能扔到什么时候?抛出此套接字后套接字是否仍处于打开状态,或者它是否始终处于关闭状态并准备好进行垃圾收集等。
这是我目前拥有的代码,我真的不知道如何正确处理断开连接。目前我认为如果在套接字等待一行时调用disconnect 方法,这可能会导致死锁,因为disconnect 将在套接字上调用close。这将在readLine 上抛出IOException,这将导致该catch 块再次调用disconnect。
public class SocketManager {
private Socket socket = null;
private PrintWriter out = null;
private BufferedReader in = null;
private String ip;
private int port;
private Object socketLock = new Object();
public SocketManager(String ip, int port) {
this.ip = ip;
this.port = port;
}
public void connect() throws UnableToConnectException, AlreadyConnectedException {
synchronized(socketLock) {
if (socket == null || socket.isClosed()) {
throw (new AlreadyConnectedException());
}
try {
socket = new Socket(ip, port);
out = new PrintWriter(socket.getOutputStream(), true);
in = new BufferedReader(new InputStreamReader(socket.getInputStream()));
} catch (IOException e) {
throw (new UnableToConnectException());
}
new Thread(new SocketThread()).start();
}
}
public void disconnect() throws NotConnectedException {
synchronized(socketLock) {
if (isConnected()) {
throw (new NotConnectedException());
}
try {
socket.close();
} catch (IOException e) {}
}
}
public boolean isConnected() {
synchronized(socketLock) {
return (socket != null && !socket.isClosed());
}
}
private class SocketThread implements Runnable {
@Override
public void run() {
String inputLine = null;
try {
while((inputLine = in.readLine()) != null) {
// do stuff
}
if (isConnected()) {
try {
disconnect();
} catch (NotConnectedException e) {}
}
} catch (IOException e) {
// try and disconnect (if not already disconnected) and end thread
if (isConnected()) {
try {
disconnect();
} catch (NotConnectedException e1) {}
}
}
}
}
}
我基本上想知道实现以下目标的最佳方法:
- 编写连接到套接字的连接方法并启动一个单独的线程来侦听输入。
- 编写断开与套接字断开连接并终止正在侦听输入的线程的断开方法。
- 处理与远程套接字的连接断开的情况。
我已经阅读了java tutorial on sockets,但我认为它并没有真正详细介绍这些内容。
谢谢!
【问题讨论】:
标签: java multithreading sockets thread-safety synchronized