在我的java应用程序中,我有一个TCP服务器,它将我的应用程序中生成的数据发送到所有连接的客户端。对于每个新套接字,我创建一个新线程。以下是线程代码。
public void run() {
try {
PrintStream printStream = new PrintStream(socket.getOutputStream(), true);
while (true) {
if (socket.isClosed()) {
break;
}
synchronized (DataSource.getInstance()) {
printStream.println(DataSource.getInstance().getData());
try {
DataSource.getInstance().wait();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
} catch (IOException e) {
e.printStackTrace();
}
}
当新数据可用时,数据生成线程写入DataSoure
并调用notifyAll()
,以便处理连接套接字的所有线程唤醒并向客户端发送可用数据。
我的问题是,即使客户端断开连接,socket.isClosed()
也会返回true。所以处理套接字的线程永远不会被终止。
为什么会这样?当客户端断开连接时,如何退出线程?
答案 0 :(得分:9)
TCP没有“断开连接”。对等体只能表明它不想再发送任何东西(发送FIN),但这并不意味着它不想接收任何东西。另一端只有在尝试读取时才意识到读取是不需要的并且返回RST。
如果您将“不想阅读”作为客户端关闭的指示(如果应用程序协议是这样的话,那么您可以通过简单地从套接字读取来测试对等体是否“断开连接”)。系统调用然后返回没有错误但是0字节,这意味着将不再有来自对等体的数据。在Java中,这种情况被转换为EOFException。
除此之外,套接字不会自动关闭 - 只能显式关闭。只有在本地端显式关闭套接字而不是对等端时,isClosed
才返回true。并且isConnected
也不会告诉你另一端是否“断开连接”,它只会告诉你你的结尾是否连接到同伴。
另见Java Socket API: How to tell if a connection has been closed?。
答案 1 :(得分:0)
您应该使用isConnected()
函数而不是isClosed()
来检测远程套接字是否已关闭。