我有一些生成套接字系結的 Java 代碼。很難提供一個最小的示例,因為這是 Web 框架的一部分,但它在某些時候有效地進行了檢查。
private static boolean portInUse(int port) {
// try to bind to this port, if it succeeds the port is not in use
try (ServerSocket socket = new ServerSocket(port)) {
socket.setReuseAddress(true);
return false;
} catch (IOException e) {
return true;
}
}
我可以看到,如果我使用相同的埠運行兩個不同的 Java 行程,它們都屬于第一個條件和 return false,因此兩者都能夠系結到同一個埠。我已經閱讀了一些相關的套接字問題和解釋,例如這個,但它們似乎聽起來好像我指定的選項不可能做到這一點。看它的實作setReuseAddress似乎只SO_REUSEADDR在套接字上設定。
我可以看到一個行程以ServerSocket[addr=0.0.0.0/0.0.0.0,localport=56674]除錯器中的套接字結束。如果我運行類似的東西,sudo lsof -n -i | grep -e LISTEN -e ESTABLISHED | grep 56674我可以看到兩個行程系結到同一個埠:
java 68863 natdempk 1256u IPv4 0xbbac93fff9a6e677 0t0 TCP *:56674 (LISTEN)
java 68998 natdempk 985u IPv6 0xbbac93fff2f84daf 0t0 TCP *:56674 (LISTEN)
我還可以看到一些其他專案,如 gRPC 和 Node,在問題跟蹤器中通過他們的服務器觀察到這種行為,但他們從未解釋為什么這是可能的。不同的行程如何系結到 macOS 上的同一個套接字?
如果這有幫助的話,我正在運行 macOS 11.6.3 (20G415)。如果有人有任何我應該在此處添加的內容,也很高興提供更多除錯資訊。
uj5u.com熱心網友回復:
它們沒有系結到同一個埠。一種是系結到 IPv6 之上的 TCP,另一種是系結到 IPv4 之上的 TCP。
稍微擴展一下 Java 細節:new ServerSocket(port)在 Java 中使用InetAddress.anyLocalAddress(),因為沒有InetAddress傳入。InetAddress.anyLocalAddress()可以回傳 IPv4 或 IPv6 地址,這意味著盡管傳遞了相同的埠,但不能保證跨 JVM 系結到相同的值在。
轉載請註明出處,本文鏈接:https://www.uj5u.com/qukuanlian/426699.html
下一篇:Python套接字掛起連接/接受
