You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

jmDNS在Windows 11的Eclipse中正常运行但MacOS Monterey下失效

问题背景

我目前在维护SourceForge上已停止更新的Java应用kmttg,这款应用可以让Tivo设备用户通过电脑编辑修改Tivo上的OnePass条目。该应用的RPC证书下月即将过期,我正在尝试修复这个问题,已经从SourceForge拉取了代码,当前在多台设备上调试运行。

  • 调试设备1:Windows 11系统笔记本,安装Java版Eclipse 2021-09(4.2.1.0)
  • 调试设备2:搭载M1 Pro芯片的14寸MacBook Pro,运行MacOS Monterey系统,安装同版本Java版Eclipse
  • 两台设备Java JRE版本均为10.0.2,代码合规级别设为1.8,依赖Jar包完全一致,均来自SourceForge原项目
问题现象

应用获取本地IP地址的逻辑在Windows 11上运行正常,但在MacBook Pro上运行失败,执行获取IP的代码后Mac设备返回IP为0.0.0.0。

问题代码段
package com.tivo.kmttg.main;

import java.net.DatagramSocket;
import java.net.InetAddress;
//import java.util.Date;
import java.util.Enumeration;
import java.util.Hashtable;
import java.util.Stack;

import javax.jmdns.JmDNS;
import javax.jmdns.ServiceInfo;

import com.tivo.kmttg.util.log;

public class mdns {
   private JmDNS jmdns = null;
   private Hashtable<String,ServiceInfo> SERVICE = new Hashtable<String,ServiceInfo>();
   //private int timeout = 5;          // ~mins after which mdns listening disabled
   //private long start_time;

   public mdns() {
      try {
         DatagramSocket socket = new DatagramSocket();
         socket.connect(InetAddress.getByName("8.8.8.8"), 10002);
         InetAddress IP = socket.getLocalAddress();  // 该逻辑在Windows 11上正常,Mac上失败
         if (! IP.isReachable(3000))
            IP = InetAddress.getLocalHost();
         if (! IP.isReachable(3000))
            log.error("mdns error: Can't determine valid IP for host running kmttg");
         //log.print("IP=" + socket.getLocalAddress().getHostAddress());
         jmdns = JmDNS.create(IP);
         socket.close();
         //start_time = new Date().getTime();
      } catch (Exception e) {
         log.error("mdns error: " + e.getMessage());
      } 
   }
}
运行截图

运行失败截图1
运行失败截图2

解决方案

这个问题是MacOS(尤其是Apple Silicon架构设备)的网络栈实现和Windows存在差异导致的:

  1. 你当前通过连接公网地址8.8.8.8获取本地出口IP的逻辑,在Mac上如果系统没有开启IPv4优先、或者当前网络没有公网连通性时,socket.getLocalAddress()会返回通配地址0.0.0.0,这是BSD系网络栈的常见行为,和Windows的实现逻辑不同。
  2. 后续的InetAddress.getLocalHost()在Mac上默认会返回loopback地址127.0.0.1或者::1,而不是物理网卡的实际IP,这是MacOS的默认hosts配置导致的。

你可以替换原有的IP获取逻辑,改为遍历所有物理网卡,筛选出非回环、非虚拟、已启动的IPv4地址,示例实现如下:

import java.net.Inet6Address;
import java.net.NetworkInterface;

private InetAddress getLocalHostLANAddress() throws Exception {
    // 优先返回可连通公网的出口地址
    try {
        DatagramSocket socket = new DatagramSocket();
        socket.connect(InetAddress.getByName("8.8.8.8"), 10002);
        InetAddress address = socket.getLocalAddress();
        if (!address.isLoopbackAddress() && !address.isAnyLocalAddress()) {
            socket.close();
            return address;
        }
        socket.close();
    } catch (Exception e) {
        // 忽略异常,走 fallback 逻辑
    }

    // Fallback:遍历所有网卡找有效IP
    InetAddress candidateAddress = null;
    for (Enumeration<NetworkInterface> ifaces = NetworkInterface.getNetworkInterfaces(); ifaces.hasMoreElements(); ) {
        NetworkInterface iface = ifaces.nextElement();
        // 跳过回环、虚拟、未启用的网卡
        if (iface.isLoopback() || iface.isVirtual() || !iface.isUp()) {
            continue;
        }
        for (Enumeration<InetAddress> inetAddrs = iface.getInetAddresses(); inetAddrs.hasMoreElements(); ) {
            InetAddress inetAddr = inetAddrs.nextElement();
            // 跳过回环地址和IPv6地址
            if (inetAddr.isLoopbackAddress() || inetAddr instanceof Inet6Address) {
                continue;
            }
            if (inetAddr.isSiteLocalAddress()) {
                // 找到内网地址直接返回
                return inetAddr;
            } else if (candidateAddress == null) {
                // 暂存非内网的公网地址备选
                candidateAddress = inetAddr;
            }
        }
    }
    if (candidateAddress != null) {
        return candidateAddress;
    }
    // 最后兜底用localhost地址
    return InetAddress.getLocalHost();
}

把原来的InetAddress IP = socket.getLocalAddress();替换为调用这个方法即可,兼容Windows、MacOS、Linux多平台。

内容的提问来源于stack exchange,提问作者rpetruzz

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.09.25 22:06:04