ios - 如何限制 DNSService 到环回接口(interface)?

标签 ios network-programming mdns

我正在尝试通过 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/

相关文章:

ios - 通用链接。无与伦比的性格

linux - 重新启动后新的 IP 地址不再保留

c - 以编程方式获取 OSX 上网络设备的多播组成员身份

android - 如何更改 NsdManager 使用的 android 设备名称?

ios - 如何在 Sprite 工具包中使用新的每像素 SkPhysics Bodies

ios - 将工具栏中的栏按钮放置在 Storyboard的中心(纵向和横向)

macos - 如何找出我的多播 (Bonjour) 主机名?

google-chrome - 如何在 chrome 打包应用程序上查找 mDNS 实例名称?

ios - 推送到 UIStoryboard 中的 Root View Controller

ios - 是否可以通过某种方式将 IPV6 地址转换为 IPV4 地址,或者始终检索 IPV4 地址?