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

Lah*_*ima 5 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();
        }
    }
Run Code Online (Sandbox Code Playgroud)

数据生成线程写入DataSoure新数据可用时调用,notifyAll()以便处理连接套接字的所有线程唤醒并向客户端发送可用数据.

我的问题是,即使客户端断开连接,也会socket.isClosed()返回true.因此处理套接字的线程永远不会被终止.

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

Ste*_*ich 9

与TCP没有"脱节".对等体只能表明它不想再发送任何东西(发送FIN),但这并不意味着它不想接收任何东西.另一端只有在尝试读取并且获得RST后才意识到读取也是不需要的.

如果您将"不想阅读"作为客户端关闭的指示(如果应用程序协议是这样的话,那么您可以通过简单地从套接字读取来测试对等体是否"断开连接").系统调用然后返回没有错误但是0字节,这意味着将不再有来自对等体的数据.在Java中,这种情况被转换为EOFException.

除此之外,套接字不会自动关闭 - 只能显式关闭.isClosed只有在本地端显式关闭套接字而不是对等端才会返回true.并且isConnected也不会告诉你,如果另一端"断开连接",它只会告诉你你的终端是否连接到同伴.

另请参阅Java Socket API:如何判断连接是否已关闭?.