我正在尝试通过 bonjour 服务实现两个 iOS 应用程序之间的通信。先不讨论这个很可能不会被App-Store审核接受。无论如何,它不会在商店中发布。
我正在尝试将服务的 Bonjour 公告限制到环回接口(interface)以仅允许同一设备上的连接。
我已经实现了低级别的 DNSServiceRegister 方法来通过以下方式发布服务:
DNSServiceErrorType err = DNSServiceRegister(
&dnsServiceRef,
kDNSServiceFlagsDefault,
if_nametoindex("lo0"), //limit to loopback interface
"myServiceName",
"_myservicetype._tcp",
NULL,
NULL,
htons(port),
0,
NULL,
&DNSServiceRegisterCallback,
(__bridge void *)(self)
);
在客户端,我按如下方式实现了发现:
DNSServiceErrorType error = DNSServiceBrowse(&serviceBrowseRef,
kDNSServiceFlagsDefault,
if_nametoindex("lo0"), //limit discovery to loopback as well
"_myservicetype._tcp",
NULL,
&serviceBrowseReply,
(__bridge void *)(self)
);
在 iPhone 模拟器中测试未返回预期结果。发现没有找到公布的服务。
一些进一步的挖掘:
尝试检查命令行是否有效 dns-sd -B _myservicetype._tcp
但它什么也没找到
奇怪的是,以下 dns-sd -lo -B _myservicetype._tcp
(限制为所有本地接口(interface)而不是环回)显示预期的服务,但 interfaceIndex 为 0(但 if_nametoindex 表示索引为 1 )
使用 kDNSServiceInterfaceIndexLocalOnly
而不是 if_nametoindex("lo0")
作为 DNSServiceBrowse
的参数返回公布的服务。
回调中报告的 interfaceIndex 再次为 0(与命令行工具的行为相同)。
更奇怪的是,如果我在注册服务时使用kDNSServiceInterfaceIndexLocalOnly
,发现服务的接口(interface)索引是 4294967295。(uint 溢出?)
这是预期的行为(不允许限制到环回接口(interface)吗?)还是我在此处对接口(interface)索引的内部处理遇到了一些奇怪的错误?
最佳答案
使用 lo0 不起作用的原因是 mDNSResponder 在注册真实接口(interface)(支持多播环回,IP_MULTICAST_LOOP)时不使用环回接口(interface)。参见 UpdateInterfaceList在 MacOS X 后端
DNS SD API 有特殊情况的索引定义,它们不是从 if_nametoidex() 返回的有效索引。通常索引从 1 开始,请参阅 dns_sd.h 中的文档关于 0 和 -1 的意思。请遵循有关如何宣传和浏览仅限本地服务的指南:
/*
* Constants for specifying an interface index
*
* Specific interface indexes are identified via a 32-bit unsigned integer returned
* by the if_nametoindex() family of calls.
*
* If the client passes 0 for interface index, that means "do the right thing",
* which (at present) means, "if the name is in an mDNS local multicast domain
* (e.g. 'local.', '254.169.in-addr.arpa.', '{8,9,A,B}.E.F.ip6.arpa.') then multicast
* on all applicable interfaces, otherwise send via unicast to the appropriate
* DNS server." Normally, most clients will use 0 for interface index to
* automatically get the default sensible behaviour.
*
* If the client passes a positive interface index, then for multicast names that
* indicates to do the operation only on that one interface. For unicast names the
* interface index is ignored unless kDNSServiceFlagsForceMulticast is also set.
*
* If the client passes kDNSServiceInterfaceIndexLocalOnly when registering
* a service, then that service will be found *only* by other local clients
* on the same machine that are browsing using kDNSServiceInterfaceIndexLocalOnly
* or kDNSServiceInterfaceIndexAny.
* If a client has a 'private' service, accessible only to other processes
* running on the same machine, this allows the client to advertise that service
* in a way such that it does not inadvertently appear in service lists on
* all the other machines on the network.
*
* If the client passes kDNSServiceInterfaceIndexLocalOnly when browsing
* then it will find *all* records registered on that same local machine.
* Clients explicitly wishing to discover *only* LocalOnly services can
* accomplish this by inspecting the interfaceIndex of each service reported
* to their DNSServiceBrowseReply() callback function, and discarding those
* where the interface index is not kDNSServiceInterfaceIndexLocalOnly.
*
* kDNSServiceInterfaceIndexP2P is meaningful only in Browse, QueryRecord,
* and Resolve operations. It should not be used in other DNSService APIs.
*
* - If kDNSServiceInterfaceIndexP2P is passed to DNSServiceBrowse or
* DNSServiceQueryRecord, it restricts the operation to P2P.
*
* - If kDNSServiceInterfaceIndexP2P is passed to DNSServiceResolve, it is
* mapped internally to kDNSServiceInterfaceIndexAny, because resolving
* a P2P service may create and/or enable an interface whose index is not
* known a priori. The resolve callback will indicate the index of the
* interface via which the service can be accessed.
*
* If applications pass kDNSServiceInterfaceIndexAny to DNSServiceBrowse
* or DNSServiceQueryRecord, they must set the kDNSServiceFlagsIncludeP2P flag
* to include P2P. In this case, if a service instance or the record being queried
* is found over P2P, the resulting ADD event will indicate kDNSServiceInterfaceIndexP2P
* as the interface index.
*/
#define kDNSServiceInterfaceIndexAny 0
#define kDNSServiceInterfaceIndexLocalOnly ((uint32_t)-1)
#define kDNSServiceInterfaceIndexUnicast ((uint32_t)-2)
#define kDNSServiceInterfaceIndexP2P ((uint32_t)-3)
关于ios - 如何限制 DNSService 到环回接口(interface)?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/38735353/