You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

关闭Scanner引发无限循环:Java Socket端口输入异常咨询

关于Java Sockets读取端口时Reader.close()导致异常的问题解析

嘿,这个坑我当初刚学Java Socket的时候也踩过!咱们来把这个问题掰扯明白:

问题根源:你关闭的不是Reader,是全局的System.in!

你用来读取控制台输入的BufferedReader,底层是绑定到标准输入流System.in的(也就是你写的new InputStreamReader(System.in)这一层)。当你调用reader.close()时,这个方法会递归关闭它包裹的所有底层流——也就是说,你不仅关了BufferedReader,连System.in也被一起关闭了!

而System.in是一个全局唯一、只能打开一次的流:一旦被关闭,后续任何尝试从它读取数据的操作都会直接抛出IOException,而且这个流根本没法重新打开。这就是为什么第一次端口占用后你关闭Reader,第二次再尝试读取时就会触发异常,进而导致无限循环(因为异常没被正确处理,程序一直重复尝试读取但永远失败)。

解决方案:不要随意关闭关联System.in的Reader

正确的做法是:只初始化一次关联System.in的Reader,在整个程序生命周期内复用它,直到程序结束再考虑关闭(甚至可以不用手动关闭,JVM退出时会自动清理标准流资源)。

举个简单的正确示例:

public class ServerPortTest {
    public static void main(String[] args) {
        // 只初始化一次Reader,绑定System.in
        try (BufferedReader reader = new BufferedReader(new InputStreamReader(System.in))) {
            while (true) {
                System.out.print("请输入服务器端口:");
                String portInput = reader.readLine();
                
                // 处理用户输入EOF的情况(比如Ctrl+D)
                if (portInput == null) {
                    System.out.println("输入结束,程序退出");
                    break;
                }

                try {
                    int port = Integer.parseInt(portInput);
                    ServerSocket serverSocket = new ServerSocket(port);
                    System.out.println("服务器在端口" + port + "启动成功!");
                    // 这里可以添加服务器逻辑
                    serverSocket.close();
                    break;
                } catch (NumberFormatException e) {
                    System.out.println("输入无效,请输入数字格式的端口号!");
                } catch (IOException e) {
                    System.out.println("端口" + portInput + "已被占用,请重新输入!");
                }
            }
        } catch (IOException e) {
            System.out.println("读取输入时发生异常:" + e.getMessage());
        }
    }
}

这里用了try-with-resources语法,会在程序结束时自动关闭Reader,既保证了资源清理,又不会在循环中提前关闭System.in。

补充说明:为什么会触发无限循环?

当你第一次关闭Reader导致System.in被关闭后,第二次调用reader.readLine()会直接抛出IOException。如果你的代码没有捕获这个异常(或者捕获后没有跳出循环、处理输入失败的情况),程序就会一直进入循环体,反复尝试读取失败的输入,最终陷入无限循环。

内容的提问来源于stack exchange,提问作者Pierre Anken

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.20 07:14:52