ServerSocket - 是否真的有必要关闭()它?

Eri*_*ans 10 java serversocket

我有这个该死的结构:

public void run() {

        try {
            if (!portField.getText().equals("")) {              
                String p = portField.getText();
                CharSequence numbers = "0123456789";

            btnRun.setEnabled(false);

            if (p.contains(numbers)) {
                ServerSocket listener = new ServerSocket(Integer.parseInt(p));

                while (true) {
                    Socket socket = listener.accept();
                    try {
                        PrintWriter out = new PrintWriter(socket.getOutputStream(), true);
                        out.println("Hi there, human.");    
                    } finally {
                        socket.close(); 
                    }
                }} else {
                    JOptionPane.showMessageDialog(null, "Only numbers are allowed.");
                }
            }

        } catch (NumberFormatException | HeadlessException | IOException e) {
            e.printStackTrace();
        } 
    }
Run Code Online (Sandbox Code Playgroud)

正如您所看到的,我需要完全像使用套接字一样关闭侦听器.问题是,如果我在循环后尝试这样做,代码将"无法访问",如果我尝试在ServerSocket的任何地方声明一个字段,我会得到一个NullPointerException.我不想与socket/client一起关闭ServerSocket,因为我想建立新的连接.

这是我的问题:

在这种情况下关闭ServerSocket真的是必要的吗?当软件关闭时,ServerSocket会自行关闭?(System.exit(0)).如果我关闭软件时继续运行ServerSocket只是因为我没有关闭它,那么我有一个问题,因为我无法达到那个血腥的代码来关闭它:).

ζ--*_*ζ-- 11

是.虽然销毁对套接字的引用可能导致垃圾收集器完成它,但是没有指定它将被关闭.这在许多情况下是特定于实现的,并且由于性能或甚至难以跟踪的微小错误,有时可能相对于设计脱轨.

保持任何地方的参考是一个肯定的赌注,即使有WeakReferences也不会.

现在,OS可以提供​​有限的(由于它的设计)插座数量.当您打开越来越多的套接字时,操作系统会受到压力并最终耗尽套接字,导致Java或其他程序失败.此外,根据您或默认设置可能设置的套接字选项,此套接字可能会发送keepalive,也会耗尽其他端点上的资源.

退出时,套接字在其构造函数中注册关闭操作以关闭它,和/或操作系统的自动清理,从而关闭它.

永远不应该依赖OS/JVM行为或完成来关闭套接字,尤其是如果您有多个套接字,即使您不打算同时使用所有套接字也是如此.


Vic*_*kin 7

是的,有必要释放任何有限的资源,否则你的应用程序会让主机上的其他进程饿死资源,并且无法长期维持

这是我如何做这样的任务:

public void run() {
    ServerSocket serverSocket = null;
    try {
        serverSocket = ... // init here
    } catch (...) {

    } finally {
        if (serverSocket != null) {
            try {
                serverSocket.close();
            } catch (IOException e) {
                // log error just in case
            }
        }
    }
}
Run Code Online (Sandbox Code Playgroud)

此外,将GUI代码移动到其他类是一个不错的主意,以保持清洁.