gpt4 book ai didi

java - JmDNS 似乎在 Mac OS X 上根本不起作用

转载 作者:太空宇宙 更新时间:2023-11-04 07:19:24 24 4
gpt4 key购买 nike

我在尝试让 JmDNS 在 Mac OS X 上工作时遇到了问题。症状是我可以发现网络上的任何服务,除了我自己计算机上的服务之外。它们是在本地主机上还是在我的计算机上运行的虚拟机上并不重要 - 无论哪种情况,它们都不会从 list 调用中返回。

我设法将我们正在做的事情浓缩为一个测试,该测试在 Windows 上通过,但在 Mac OS X 上失败。现在的问题是我无法弄清楚问题出在哪里。

@Test
public void testAdvertisingOverLoopback() throws Exception
{
// happens on any address but loopback is the strangest
InetAddress address = InetAddress.getLoopbackAddress();
String type = "_test._tcp.local.";
String name = "test-service";
int port = 9999;
Map<String, String> properties = ImmutableMap.of("key", "value");

// simulate the service starting up. issue also occurs in separate VMs
try (JmDNS serviceDns = JmDNS.create(address))
{
serviceDns.registerService(ServiceInfo.create(type, name, port,
0, 0, properties));

try (JmDNS clientDns = JmDNS.create(address))
{
ServiceInfo[] services = clientDns.list(type);

// One of the entries should:
assertThat(services, is(arrayContaining(allOf(

// Contain an address which matches the one we advertised (culling those which might
// be registered by other tests which happen to run at the same time.)
hasProperty("inetAddresses", arrayContaining(sameAddressAs(address))),

// Match the parameters we specified in the call to list.
hasProperty("application", equalTo("test")),
hasProperty("protocol", equalTo("tcp")),
hasProperty("domain", equalTo("local")),

// Match the info we advertised.
hasProperty("port", equalTo(9999)),
hasCustomProperty("key", "value")
))));
}
}
}

private static Matcher<InetAddress> sameAddressAs(final InetAddress address)
{
return new TypeSafeMatcher<InetAddress>()
{
@Override
protected boolean matchesSafely(InetAddress inetAddress)
{
return Arrays.equals(address.getAddress(), inetAddress.getAddress());
}

@Override
public void describeTo(Description description)
{
description.appendText("same address as ");
description.appendValue(address.getHostAddress());
}
};
}

private static Matcher<ServiceInfo> hasCustomProperty(final String key,
final String value)
{
return new TypeSafeMatcher<ServiceInfo>()
{
@Override
protected boolean matchesSafely(ServiceInfo serviceInfo)
{
return value.equals(serviceInfo.getPropertyString(key));
}

@Override
public void describeTo(Description description)
{
description.appendText("has custom mDNS property ");
description.appendValue(key);
description.appendText(" = ");
description.appendValue(value);
}
};
}

在调试器中,我可以看到它没有将套接字绑定(bind)到任何特定地址,只是绑定(bind)到特定端口。但随后它会将其设置为特定的接口(interface)。

我在 Wireshark 中看到的是,数据包来 self 的计算机的公共(public) IP(en0 地址),即使 lo0 是我用于测试的接口(interface)。我还看到查询和响应数据包。回复正在返回。

但是在 Java 端,我看到它调用 DatagramSocket#receive(DatagramPacket) 并且从未收到数据包。

(我也花了半天时间寻找 JmDNS 的替代品,但看起来其他声称可以替代它的库实际上还不能进行多播,这使得它们有点毫无意义。:( )

这是怎么回事?

最佳答案

发生的事情是 OS X 中内置的 Zeroconf 服务正在获取数据包。

JmDNS 假定它是在监听该端口的计算机上运行的唯一守护进程。因为它使用的代码故意绑定(bind)到 0.0.0.0,所以不会抛出有关正在使用的端口的异常(显然这是 Socket API 的一个“功能”。)

对于 Windows,这工作正常,因为永远不会有另一个 Zeroconf 守护进程在运行。

对于 Mac OS X,它肯定会失败,因为内置的总是在运行。

我猜想在 Linux 上,您会得到不同的结果,具体取决于您运行的发行版以及安装的服务。

我正在解决的问题的解决方案是在 CFNetServices 之上创建一个完全不同的 API .

关于java - JmDNS 似乎在 Mac OS X 上根本不起作用,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/19533979/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com