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

时间:2017-07-26 04:27:17

标签: java sockets

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

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

2 个答案:

答案 0 :(得分:1)

对于这种类型的东西,端口可能很挑剔。他们并不打算一直打开和关闭。您应该打开套接字并只处理其中的每个连接,如下所示:

    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/

答案 1 :(得分:1)

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

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

  

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

     

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

这最终启用了SO_REUSEADDR套接字选项。有关这些套接字选项的更多详细信息,请参阅Linux socket手册页。

但是,请注意,不同平台上的确切感知行为可以非常大。特别是,请注意Windows上此设置的极端不同和危险行为,如MSDN文章Using SO_REUSEADDR and SO_EXCLUSIVEADDRUSE中所述。基本上,Windows上的SO_REUSEADDR可以允许任意进程来“偷”&#34;另一个进程已经使用的套接字,导致不确定的行为。

  

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

我建议人们仔细思考并确保您对此设置充满信心,而不是盲目地打开它。关于相关套接字选项,还有一个非常先前的问题和答案:

Socket options SO_REUSEADDR and SO_REUSEPORT, how do they differ? Do they mean the same across all major operating systems?