4

我已经使用 Bonjour API 注册了一条记录。现在我想知道我刚刚发布的记录的内容。我通过指定一个 NULL 主机名来创建它,意思是“使用守护程序的默认值”,但我找不到一个简单的方法来查询它是什么!

使用 avahi,这很容易:我调用avahi_client_get_host_name()以获取机器主机名的起始值。

对于 avahi 和 Bonjour,SRV 记录的值可以在注册的生命周期内更改 - 如果注册是使用 NULL 主机名完成的,则记录的主机名会在必要时自动更新。我在这里想要的只是一种在我执行注册时获取主机名初始值的方法。

请注意,在我的 Snow Leopard 测试机器上,默认的多播主机名来自gethostname(2).

我能想到的四个解决方案:

  1. 在我的过程中获取主机名。它可能在某个地方。我strings(3)对我的进程的内存转储进行了搜索,并在我的地址空间中找到了四个多播主机名实例,但这可能是巧合,因为该名称用于其他用途。即使我所追求的字符串在我的进程中的某个地方,我也找不到一个 API 来理​​智地检索它。
  2. 从守护进程查询主机名。可能有一些查询我可以通过 mach 端口发送到获取它的守护进程?我再也找不到 API 了。相关的代码块在 mDNSResponder 的 uDNS.c 文件中,并且似乎没有通过 RPC 接口公开。
  3. 我可以查找我注册的服务。不过,这可能会涉及一些网络流量,所以除非有一些保证不会发生,否则我不愿意这样做。
  4. 重新实现 uDNS.c 中的逻辑。它从以下组合中获取机器的主机名:

    • 动态 DNS 配置
    • 静态配置的多播主机名
    • 反向查找主接口的 IPv4 地址
    • 它特别不使用gethostname(2)或等效

    重新实现该逻辑似乎是不可行的。

目前,我倾向于进行查找以获取初始 SRV 注册的值,但这似乎并不理想。什么是正确的解决方案?

4

4 回答 4

2

我需要这样做。您想使用 ConvertDomainNameToCString 宏(包含在 mDNSEmbeddedAPI.h 中),并且需要访问核心 mDNS 结构。

以下是您获得已注册的确切 Bonjour/Zeroconf 主机名的方法:

char szHostname[512];
extern mDNS m;

ConvertDomainNameToCString(&m.MulticastHostname, szHostname);

我希望这可以帮助你。

于 2013-09-03T15:51:54.453 回答
0

作为记录,我使用 (4),获取机器的配置以将守护程序正在使用的主机名汇总在一起,而无需查询它。

static char* getBonjourDefaultHost()
{
  char* rv = 0;
#ifdef __APPLE__
  CFStringRef name = SCDynamicStoreCopyLocalHostName(NULL);
  if (name) {
    int len = CFStringGetLength(name);
    rv = new char[len*4+1];
    CFStringGetCString(name, rv, len*4+1, kCFStringEncodingUTF8);
    CFRelease(name);
  }
  // This fallback is completely incorrect, but why should we care...
  // Mac does something crazy like <sysctl hw.model>-<MAC address>.
  if (!rv)
    rv = GetHostname(); // using gethostname(2)

#elif defined(WIN32)
  CHAR tmp[256+1];
  ULONG namelength = sizeof(tmp);
  DynamicFn<BOOL (WINAPI*)(COMPUTER_NAME_FORMAT,LPSTR,LPDWORD)>
    GetComputerNameExA_("Kernel32", "GetComputerNameExA");
  if (!GetComputerNameExA_.isValid() ||
      !(*GetComputerNameExA_)(ComputerNamePhysicalDnsHostname, tmp, &namelength))
    tmp[0] = 0;
  // Roughly correct; there's some obscure string cleaning mDNSResponder does
  // to tidy up funny international strings.
  rv = tmp[0] ? strdup(tmp) : strdup("My Computer");

#elif defined(__sun)
  // This is exactly correct! What a relief.
  rv = GetHostName();

#else
#error Must add platform mDNS daemon scheme
#endif
  return rv;
}
于 2013-11-07T13:20:50.717 回答
0

从命令行可以使用以下scutil命令获取本地 (Bonjour) 主机名:

scutil --get LocalHostName

以编程方式,这可以通过框架使用kSCPropNetLocalHostName密钥获得。SystemConfiguration

于 2017-10-11T18:35:33.910 回答
0

我知道这已经得到了回答,但是我根据 Pierz 在他回答的后半部分所说的话,去看看如何使用 SystemConfiguration 框架来做到这一点。

这就是我的工作,认为它可能会节省其他人在谷歌上搜索的时间:在 Swift 中:

import SystemConfiguration

    let store = SCDynamicStoreCreate(nil, "ipmenu" as CFString, nil, nil )
    if let hostNames = SCDynamicStoreCopyValue(store, "Setup:/Network/HostNames" as CFString){
        if let hostName:String = (hostNames[kSCPropNetLocalHostName]) as? String {
            print("Host name:\(hostName)")
        }
    }
于 2020-10-21T22:07:02.800 回答