java - 为什么两个 Java 进程可以绑定(bind)到 macOS 中的同一个套接字?

标签 java macos sockets networking serversocket

我有一些生成套接字绑定(bind)的 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 进程,它们都会落入第一个条件并返回 false,因此它们都能够绑定(bind)到相同的端口。我已经通读了 some related socket questions and explanations like this one ,但他们似乎使我指定的选项听起来不可能。查看 setReuseAddress 的实现,它似乎只在套接字上设置了 SO_REUSEADDR

我可以看到一个进程在调试器中以类似 ServerSocket[addr=0.0.0.0/0.0.0.0,localport=56674] 的套接字结束。如果我运行类似 sudo lsof -n -i | 的东西grep -e LISTEN -e 已建立 | grep 56674 我可以看到两个进程绑定(bind)到同一个端口:

java      68863    natdempk 1256u  IPv4 0xbbac93fff9a6e677      0t0  TCP *:56674 (LISTEN)
java      68998    natdempk  985u  IPv6 0xbbac93fff2f84daf      0t0  TCP *:56674 (LISTEN)

我还可以看到 gRPC 和 Node 等其他一些项目在问题跟踪器中提到了在他们的服务器上观察到的这种行为,但他们从未解释为什么这是可能的。 不同的进程如何绑定(bind)到 macOS 上的同一个套接字?

如果有帮助的话,我正在运行 macOS 11.6.3 (20G415)。如果有人有任何我应该在此处添加的内容,也很乐意提供更多调试信息。

最佳答案

它们没有绑定(bind)到同一个端口。一种是绑定(bind)到 IPv6 之上的 TCP,另一种是绑定(bind)到 IPv4 之上的 TCP。

稍微扩展一下 Java 细节:Java 中的 new ServerSocket(port) 使用 InetAddress.anyLocalAddress() 因为没有 InetAddress InetAddress.anyLocalAddress() 可以返回 IPv4 或 IPv6 地址,这意味着尽管传入了相同的端口,但不能保证绑定(bind)到 JVM 的值相同。

关于java - 为什么两个 Java 进程可以绑定(bind)到 macOS 中的同一个套接字?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/71148158/

相关文章:

带有 Cookie 的 Objective-C 异步 Web 请求

java - 安卓服务器: why it times out incoming connections randomly?

python - 安装后 awscli 未添加到路径

objective-c - 如何检测 OS X 上的麦克风使用情况?

Java - 按子列表大小对列表进行排序

java - 如何在android中将ListActivities添加到ViewPager中?

c - 我如何使用此客户端程序访问 tomcat 资源?

C++套接字设计

java - 我需要让所有类都不可变吗?

java - 一些 Perl 行不会从 Java Runtime.getRuntime().exec() 执行