美文网首页IOT
mDNS Protocol 在iOS上的应用

mDNS Protocol 在iOS上的应用

作者: 起个名字想破头 | 来源:发表于2020-12-18 11:23 被阅读0次

    概念

    mdns多播dns(Multicast Domain Name System)mDNS主要实现了在没有传统DNS服务器的情况下使局域网内的主机实现相互发现和通信。在局域网中,设备和设备之前相互通信是需要知道对方的ip地址的,大多数情况,设备的ip不是静态ip地址,而是通过dhcp协议动态分配的ip 地址,此时就可以使用mdns协议来发现设备,并解析出设备的ip地址,来进行通信。

    原理

    这个真没研究,看rfc文档吧,如果了解dns协议,看这个会轻松很多。https://www.rfc-editor.org/rfc/rfc6762.html

    网上很多文章在介绍原理时有如下介绍:每个进入局域网的主机,如果开启了 mDNS 服务的话,都会向局域网内的所有主机组播一个消息,我是谁,和我的IP地址是多少。然后其他也有该服务的主机就会响应,也会告诉你,它是谁,它的 IP 地址是多少,可以简单通过这段话来理解。

    示例代码

    服务端的代码这里就不写了,下面提供一下iOS使用Objective-C,启动mdns并发现设备的代码

    - (void)viewDidLoad {
        [super viewDidLoad];
        // Do any additional setup after loading the view.
       
    //创建一个browser实例,该对象的运行需要在runloop中,请注意 
        self.browser = [[NSNetServiceBrowser alloc] init];
        self.browser.delegate = self;
    
        //调用下面方法后,就开始查询网络内所有的设备
        //type参数要按照自己的需要进行填充,下面仅作示例,即服务端启动时是什么协议,这里就用什么协议
        //domain参数可以为空,默认按照local.处理
        [self.browser searchForServicesOfType:@"_http._tcp" inDomain:@""];
        
    }
    
    - (void)printAddress {
        if (self.service.addresses.firstObject == nil) {
            NSLog(@"zero address");
            return;
        }
    
        //这里在mdns将域名解析出ip地址后,address中是个sockaddr结构体,可以按照如下方式解析出具体ip和port
        struct sockaddr_in *addr = (struct sockaddr_in *)(self.service.addresses.firstObject.bytes);
        NSString *ip = [NSString stringWithUTF8String:inet_ntoa(addr->sin_addr)];
        NSInteger port = ntohs(addr->sin_port);
        
        NSLog(@"ip:%@, port:%d", ip, port);
    
    }
    
    - (void)printTxtRecord:(NSData *)data {
        //通过系统代理收到的设备文本记录为NSData对象,可以按照下面方式转出具体的数据
        NSDictionary *dict = [NSNetService dictionaryFromTXTRecordData:data];
        [dict enumerateKeysAndObjectsUsingBlock:^(id  _Nonnull key, id  _Nonnull obj, BOOL * _Nonnull stop) {
            NSLog(@"key:%@, value:%@", key, [[NSString alloc] initWithData:obj encoding:NSUTF8StringEncoding]);
        }];
    
    }
    
    #pragma mark - NSNetServiceBrowserDelegate
    
    //通过上面调用[self.browser searchForServicesOfType:@"_http._tcp" inDomain:@"local."]方法
    //如果局域网内搜到设备,会通过该代理回调
    - (void)netServiceBrowser:(NSNetServiceBrowser *)browser didFindService:(NSNetService *)service moreComing:(BOOL)moreComing {
        NSLog(@"%s, service:%@, moreComing:%d", __FUNCTION__, service, moreComing);
        
        if ([service.name isEqualToString:@"240A64C9DFE8"]) {
            
            NSLog(@"name:%@, type:%@, domain:%@, hostName:%@",
                  service.name,
                  service.type,
                  service.domain,
                  service.hostName);
            
            self.service = service;
            self.service.delegate = self;
            
            //下面两个操作可以并行,通过测试,通常文本记录能够快速返回,而ip解析是耗时的
    
            //开始监听文本记录
            [self.service startMonitoring];
            //开始进行ip解析
            [self.service resolveWithTimeout:5.f];
        }
    
    }
    
    //当设备从局域网内消失时会通过该方法回调
    - (void)netServiceBrowser:(NSNetServiceBrowser *)browser didRemoveService:(NSNetService *)service moreComing:(BOOL)moreComing {
        NSLog(@"%s, service:%@, moreComing:%d", __FUNCTION__, service, moreComing);
    }
    
    #pragma mark - NSNetServiceDelegate
    
    //调用resolveWithTimeout解析成功后,会通过该方法回调
    - (void)netServiceDidResolveAddress:(NSNetService *)sender {
        NSLog(@"%s", __FUNCTION__);
    
        [self printAddress];
    }
    
    //调用startMonitoring后会通过该方法回调,如果数据发生更新,该方法也会进行回调
    - (void)netService:(NSNetService *)sender didUpdateTXTRecordData:(NSData *)data {
        NSLog(@"%s", __FUNCTION__);
        
        [self printTxtRecord:data];
    }
    
    

    IOT应用

    iot领域,智能家居设备作为局域网内的一个设备,需要被手机app发现并与设备进行通信。此时就可以使用mdns协议来实现。
    设备端需要注册并发布mdns服务。通常需要提供主机名,协议类型和端口号。另外,mdns还可以提供一些文本记录,作为附加数据,供手机app端获取。
    手机app根据协议类型启动一个mdns服务来查询局域网内的设备,并获取ip, port, 附加数据内容。从而与手机建立连接,进行通信。

    相关文章

      网友评论

        本文标题:mDNS Protocol 在iOS上的应用

        本文链接:https://www.haomeiwen.com/subject/utlogktx.html