我正在尝试使用 Windows 10+ API DnsServiceRegister 来注册可发现的 Web 服务器。
DNS_SERVICE_REGISTER_REQUEST rd = {};
DNS_SERVICE_INSTANCE di = {};
rd.pServiceInstance = &di;
rd.unicastEnabled = 0;
di.pszInstanceName = L"Remote Control._http._tcp.local";
di.pszHostName = L"192.168.10.6";
IP4_ADDRESS i4 = {};
InetPton(AF_INET, L"192.168.10.6", (void*)&i4);
di.ip4Address = &i4;
di.wPort = (WORD)12345;
rd.Version = DNS_QUERY_REQUEST_VERSION1;
rd.pRegisterCompletionCallback = [](DWORD Status,
PVOID pQueryContext,
PDNS_SERVICE_INSTANCE pInstance)
{
nop();
};
DnsServiceRegister(&rd, 0);
调用成功(根据文档返回值 DNS_REQUEST_PENDING),过了一会儿,我的回调被调用,状态 = 0(成功?)。但是,没有 UPnP 工具检测到我的服务。 当我将单播设置为 1 时,状态为 9002(错误)。
使用此 API 时我缺少什么?
编辑:调用回调时,pInstance 参数指向带有 ip4Address 和 ip6Address 空指针的 DNS_SERVICE_INSTANCE。为什么?
编辑:可以使用 DnsServiceBrowse() 发现它。但 UPnP 扫描工具无法发现它。
di.pszHostName = L"192.168.10.6";
不是有效的主机名。它必须是一个字符串并以 .local 结尾。
我遇到了同样的问题,我复制了您的代码片段进行测试。如果主机名是以 .local 结尾的普通名称,则它可以工作。
我复制了您的代码并做了一些小的修改,在调用 DnsServiceRegister() 和我的回调函数中获得了正确的返回值以指示事物已注册,但我从未在运行 mdns-scan 或的 linux 机器上看到结果avahi-发现。
我是否需要在这些调用之前启用 Windows 服务,或者拥有凭据句柄?
void DnsServiceRegisterComplete(
DWORD Status,
PVOID pQueryContext,
PDNS_SERVICE_INSTANCE pInstance
)
{
if (bConsoleExists)
std::cout << "[" << getTimeISO8601() << "] DnsServiceRegisterComplete(" << Status << ") DNS_ERROR_RCODE_SERVER_FAILURE=" << DNS_ERROR_RCODE_SERVER_FAILURE << std::endl;
return;
}
void TiVomDNSRegister(bool enable = true)
{
IP4_ADDRESS i4 = { 0 };
InetPton(AF_INET, L"192.168.50.32", (void*)&i4);
DNS_SERVICE_INSTANCE di = { 0 };
di.ip4Address = &i4;
di.pszInstanceName = L"WimSurface9._tivo-videos._tcp.local";
di.pszHostName = L"WimSurface9.local";
di.wPort = (WORD)80;
DNS_SERVICE_REGISTER_REQUEST rd = { 0 };
rd.Version = DNS_QUERY_REQUEST_VERSION1;
rd.InterfaceIndex = 0;
rd.pServiceInstance = &di;
rd.pRegisterCompletionCallback = &DnsServiceRegisterComplete;
rd.pQueryContext = nullptr;
rd.hCredentials = 0;
rd.unicastEnabled = FALSE; // true if the DNS protocol should be used to advertise the service; false if the mDNS protocol should be used.
if (enable)
{
auto mDNSReturn = DnsServiceRegister(&rd, nullptr);
if (bConsoleExists)
std::cout << " DnsServiceRegister(" << mDNSReturn << ") DNS_REQUEST_PENDING=" << DNS_REQUEST_PENDING << std::endl;
}
else
{
auto mDNSReturn = DnsServiceDeRegister(&rd, nullptr);
if (bConsoleExists)
std::cout << " DnsServiceRegister(" << mDNSReturn << ") DNS_REQUEST_PENDING=" << DNS_REQUEST_PENDING << std::endl;
}
}