一个答案是你真的应该close()资源..。即使这不是绝对必要的。
为什么?
因为,(假设的)情况意味着它不是绝对必要的,可能会改变!
还有..。让我们面对它..。自动关闭服务器套接字很容易编写代码。
但是继续读..。
在这种情况下,真的有必要关闭ServerSocket吗?
那得看情况。
如果您肯定知道run()只运行一次,然后应用程序总是会完全关闭(下面的模块警告),那么不关闭ServerSocket不会造成任何实际伤害。否则,未能关闭()可能会造成损害。
“伤害”可采取以下几种形式:
服务器套接字可以在端口上持有一个“锁”,从而阻止应用程序的另一个实例侦听该端口(取决于操作系统)。服务器套接字可能是有限的资源,如果多次调用run()方法(没有close()-ing),应用程序可以“获取”该资源的所有可用实例,从而阻止其他应用程序获取实例。
如果多次调用run(),也可能对应用程序实例本身造成危害。
当软件关闭时,ServerSocket会自行关闭?
除非垃圾收集并完成,否则ServerSocket不会“关闭自己”。当JVM退出时,您不能依赖这两种情况。但在更广泛的意义上,当JVM退出时,底层服务器套接字资源通常会自动关闭(释放)。
但完整的答案实际上取决于你所说的“软件被关闭”是什么意思,也取决于平台的性质。例如:
如果关闭意味着JVM完全退出,并且相应的进程“拥有”底层服务器套接字(从OS的角度来看)也会退出,那么OS将关闭该套接字.至少在现代Unix / Linux / Windows平台上。(注意Android是Linux下的)如果“软件”类似于运行在web容器中的webapp,那么“关机”对JVM退出意味着什么,而ServerSocket在关机后可以继续存在(而不是关闭)。如果JVM嵌入了其他东西(例如,在大型C/ C++应用程序中),并且其他东西没有退出,那么操作系统将不知道释放底层服务器套接字。如果您在操作系统不提供与Unix / Linux /(现代) Windows上相同级别的进程分离/资源管理的平台上运行,那么底层服务器套接字可能不会在进程退出时被OS关闭。(此场景可能适用于嵌入式系统上的Java实现.)
无论如何,做正确的事情并不难。在Java 7及更高版本中:
代码语言:javascript运行复制public void run() {
String p = portField.getText().trim();
if (p.isEmpty()) {
return;
}
btnRun.setEnabled(false);
try (ServerSocket listener = new ServerSocket(Integer.parseInt(p))) {
while (true) {
try (Socket socket = listener.accept();
PrintWriter out = new PrintWriter(
socket.getOutputStream(), true)) {
out.println("Hi there, human.");
}
}
} catch (NumberFormatException e) {
JOptionPane.showMessageDialog(null, "Only numbers are allowed.");
} catch (HeadlessException | IOException e) {
e.printStackTrace();
} finally {
btnRun.setEnabled(true); // ... possibly
}
}(不过,我不认为在从按钮侦听器调用的动作中捕获HeadlessException有什么意义。)