4

最近我遇到了嵌入式 postgres库的问题。我试图通过手动选择一个空闲端口

new ServerSocket(0).getLocalPort()

但我在某个地方遇到了竞争条件(我的测试挂在第二个测试套件启动时)。

然后我了解到该库本身具有这种能力(使用随机端口)并且它没有我遇到的问题。我分析了源代码,我发现唯一的区别是他们做了额外的检查:

try (ServerSocket socket = new ServerSocket(0)) {
    while(!socket.isBound()) {
        Thread.sleep(50);
    }
    return socket.getLocalPort();
}

所以在端口被随机化后,他们等到它被绑定。我指的代码。

我想知道为什么有这段代码。我对“绑定”的理解是它等同于在给定端口上“监听”,但在这里情况并非如此,因为此代码在服务器启动之前运行。事实上,服务器将启动(并将自身绑定)到这个确切的端口。这让我很困惑。

4

1 回答 1

2

库中的代码是对此问题的修复,其原因为

..看来 EmbeddedPostgres#detectPort 方法可能会导致问题,因为它在查询端口之前不等待绑定套接字,导致 ServerSocket#getLocalPort 返回 -1,如文档所述。

因此,如果套接字未绑定,则对ServerSocket.getLocalPort()的调用将返回,显然这可能会在调用 之后的某个时间发生,尽管尚不清楚在什么情况下。所以代码只是等待以确保它被绑定。-1new ServerSocket(0)

然而,文档并没有说任何new ServerSocket(0)不返回绑定套接字的地方。ServerSocket(int port)的 javadoc说“创建一个服务器套接字,绑定到指定的端口。”。

但是他们确实有一个问题,这是唯一的解决方法,我想它解决了这个问题......所以JDK中的文档非常不清楚?


至于绑定与聆听。绑定是分配地址和端口的部分,它仍然需要主动开始接受连接。

于 2021-02-15T15:38:03.653 回答