如何找到我的多播(Bonjour)主机名?

时间:2013-08-16 10:43:27

标签: macos networking bonjour zeroconf mdns

我使用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)或同等的

    重新实施这种逻辑似乎是不可行的。

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

4 个答案:

答案 0 :(得分:2)

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

以下是如何获得已注册的确切Bonjour / Zeroconf主机名:

char szHostname[512];
extern mDNS m;

ConvertDomainNameToCString(&m.MulticastHostname, szHostname);

我希望这会对你有所帮助。

答案 1 :(得分: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;
}

答案 2 :(得分:0)

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

scutil --get LocalHostName

以编程方式通过kSCPropNetLocalHostName框架使用SystemConfiguration密钥获取此内容。

答案 3 :(得分:0)

我知道已经回答了这个问题,但是我根据Pierz在回答的后半部分所说的内容,来看看如何使用SystemConfiguration框架来实现它。

这是我正在工作的内容,认为这可以节省其他人在一段时间内使用Google搜索: 在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)")
        }
    }