mDNS Protocol 在iOS上的应用

概念

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, 附加数据内容。从而与手机建立连接,进行通信。

©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 203,772评论 6 477
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 85,458评论 2 381
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 150,610评论 0 337
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 54,640评论 1 276
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 63,657评论 5 365
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,590评论 1 281
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 37,962评论 3 395
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,631评论 0 258
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 40,870评论 1 297
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,611评论 2 321
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,704评论 1 329
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,386评论 4 319
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 38,969评论 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 29,944评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,179评论 1 260
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 44,742评论 2 349
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,440评论 2 342

推荐阅读更多精彩内容