客户端断开连接后,Socket isClosed()返回false

时间:2015-05-31 15:50:49

标签: java sockets

在我的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。所以处理套接字的线程永远不会被终止。

为什么会这样?当客户端断开连接时,如何退出线程?

2 个答案:

答案 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()来检测远程套接字是否已关闭。