对同一端口的连续 JVM 绑定调用之间的限制



我有在特定端口上设置服务器的Java代码,一些代码在使用该服务器的python中运行,然后端口被关闭。 我已经设置了它,以便在每次 python 运行后,java 循环并重复此过程(设置新服务器、服务,然后关闭(。

我注意到当python调用很短(大约<10s(时,下次Java尝试设置此端口时,它将失败。 是否有关于在 Java 上连续设置相同端口之间必须等待多长时间的规则?

端口可能对这种事情很挑剔。它们并不意味着一直打开和关闭。您应该保持套接字打开状态,只处理其中的每个连接,如下所示:

ServerSocket listener = new ServerSocket(9090);
try {
while (true) {
Socket socket = listener.accept();
try {
PrintWriter out =
new PrintWriter(socket.getOutputStream(), true);
out.println(new Date().toString());
} finally {
socket.close();
}
}
}
finally {
listener.close();
}

(图片来源:http://cs.lmu.edu/~ray/notes/javanetexamples/(

一般来说,最好维护一个长时间运行的ServerSocket来服务多个请求,因为其他人已经回答和评论了。 但是,我发现有时需要快速连续地停止和启动服务器是合理的。 一个示例是集成测试套件,它涉及以不同的配置停止和重新启动服务器以重复测试运行。

如果您真的有此需求,那么您可能会对ServerSocket#setReuseAddress(boolean)感兴趣。

启用/禁用SO_REUSEADDR套接字选项。 当 TCP 连接关闭时,连接可能会在连接关闭后的一段时间内保持超时状态(通常称为TIME_WAIT状态或 2MSL 等待状态(。对于使用已知套接字地址或端口的应用程序,如果存在涉及套接字地址或端口的超时状态连接,则可能无法将套接字绑定到所需的套接字地址。

在使用 bind(SocketAddress( 绑定套接字之前启用SO_REUSEADDR允许绑定套接字,即使以前的连接处于超时状态也是如此。

这最终启用SO_REUSEADDR套接字选项。 有关这些套接字选项的更多详细信息,一个信息来源是 Linuxsocket手册页。

但是,请注意,在不同的平台上,确切的感知行为可能会非常大。 特别是,请注意 Windows 上此设置的极其不同和危险的行为,如 MSDN 文章使用 SO_REUSEADDR 和 SO_EXCLUSIVEADDRUSE 中所述。 基本上,Windows 上的SO_REUSEADDR可以允许任意进程"窃取"另一个进程已经在使用的套接字,从而导致不确定的行为。

SO_REUSEADDR套接字选项允许一个套接字强制绑定到另一个套接字正在使用的端口。第二个套接字调用 setsockopt,其中 optname 参数设置为 SO_REUSEADDR,optval 参数设置为 TRUE,然后在与原始套接字相同的端口上调用绑定。成功绑定第二个套接字后,绑定到该端口的所有套接字的行为是不确定的。例如,如果同一端口上的所有套接字都提供 TCP 服务,则无法保证通过该端口传入的任何 TCP 连接请求都由正确的套接字处理 — 该行为是不确定的。恶意程序可以使用SO_REUSEADDR强制绑定已用于标准网络协议服务的套接字,以拒绝对这些服务的访问。使用此选项不需要特殊权限。

我建议人们仔细考虑,并确保你对这个设置有信心,而不是盲目地打开它。 关于相关套接字选项,还有一个惊人的先验问答:

套接字选项SO_REUSEADDR和SO_REUSEPORT,它们有何不同?它们在所有主要操作系统中的含义是否相同?

最新更新