美文网首页iOS Developertom
使用GCDAsyncUdpSocket进行局域网广播寻址

使用GCDAsyncUdpSocket进行局域网广播寻址

作者: 丨n水瓶座菜虫灬 | 来源:发表于2016-11-17 17:38 被阅读374次
    局域网内app搜索智能设备
    步骤: 
    1. app连接上智能设备所连接的wifi热点
    2. app使用UdpSocket发送广播寻找设备
    3. 设备收到广播后回复自己的ip地址和mac地址
    4. 找到了对应的设备就可以进行数据通信
    
    app使用UdpSocket发送广播寻址的逻辑如下:
    1. 获取当前手机连接的wifi IP地址
    2. 把IP地址最后的数字换成255,作为目标IP, 例如 手机当前IP地址为192.168.1.1 转换为目标IP后为 192.168.1.255,这样app发送广播时192.168.1.xx的设备都能收到广播信息。
    3. 把目标IP作为Host,发送寻址指令到指定端口
    4. 开启接收监听beginReceiving
    
    获取当前手机wifi IP地址的方法如下:
    // 需要导入头文件 <ifaddrs.h>和<arpa/inet.h>
    - (NSString *)getIPAddress {
        NSString *address = @"error";
        struct ifaddrs *interfaces = NULL;
        struct ifaddrs *temp_addr = NULL;
        int success = 0;
        success = getifaddrs(&interfaces);
        if (success == 0) {
            temp_addr = interfaces;
            while (temp_addr != NULL) {
                if (temp_addr->ifa_addr->sa_family == AF_INET) {
                    if ([[NSString stringWithUTF8String:temp_addr->ifa_name] isEqualToString:@"en0"]) {
                        address = [NSString stringWithUTF8String:inet_ntoa(((struct sockaddr_in*)temp_addr->ifa_addr)->sin_addr)];
                    }
                }
                temp_addr = temp_addr->ifa_next;
            }      
        }
        freeifaddrs(interfaces);
        NSLog(@"ip:%@", address);
        return address;
    }
    

    关于ifaddrs结构体自己画的图解如下:


    ifaddrs结构体
    创建GCDAsyncUdpSocket并设置代理,启动本地端口
    self.udpSocket = [[GCDAsyncUdpSocket alloc] initWithDelegate:self delegateQueue:dispatch_get_global_queue(0, 0)];
    
    // 启动本地端口
    [self.udpSocket localPort];
    
    广播寻址的方法如下
    - (void)broadcastSearchCommandWithBlock:(BroadcastSearchCommandBlock)block {
        if (block) {// 此处的block是项目中用于回调数据
            self.broadcastBlock = block;
        }
        NSTimeInterval timeout = 1000;//发送超时时间
        NSString *request = @"Cmd%Search%End";// 查询指令,此指令与硬件、服务器沟通好
        NSData *data = [NSData dataWithData:[request dataUsingEncoding:NSASCIIStringEncoding]];
        NSLog(@"data:%@", data);
        UInt16 port = kPORT;// 端口
        NSError *error;
    
        // 发送广播设置
        [self.udpSocket enableBroadcast:YES error:&error];
    
        // 获取本地IP地址并用.分隔开放在数组中
        NSArray *strArr = [[self getIPAddress] componentsSeparatedByString:@"."];
        NSMutableArray *muArr = [NSMutableArray arrayWithArray:strArr];
        // 将数组的最后一位换成255
        [muArr replaceObjectAtIndex:(strArr.count-1) withObject:@"255"];
        // 将数组用.连接成目标IP地址字符串
        NSString *finalStr = [muArr componentsJoinedByString:@"."];// 目标ip
    
        NSLog(@"目标ip:%@", finalStr);
        // 发送广播寻址指令
        [self.udpSocket sendData:data toHost:finalStr port:port withTimeout:timeout tag:1];
    
        [self.udpSocket beginReceiving:nil];
    }
    
    实现GCDAsyncUdpSocketDelegate代理方法监听回调信息
    - (void)udpSocket:(GCDAsyncUdpSocket *)sock didReceiveData:(NSData *)data fromAddress:(NSData *)address withFilterContext:(id)filterContext {
        NSString *result;
        result = [[NSString alloc] initWithData:data encoding:NSASCIIStringEncoding];
        NSLog(@"resutl:%@",result); // 接收到的数据
        NSString *addr = [GCDAsyncUdpSocket hostFromAddress:address];// 从哪个IP地址发送来的数据
        NSLog(@"address:%@", addr);
    }
    
    - (void)udpSocket:(GCDAsyncUdpSocket *)sock didNotSendDataWithTag:(long)tag dueToError:(NSError *)error {
        NSLog(@"没有发送");
    }
    
    - (void)udpSocket:(GCDAsyncUdpSocket *)sock didSendDataWithTag:(long)tag {
        NSLog(@"已经发送");
    }
    
    - (void)udpSocketDidClose:(GCDAsyncUdpSocket *)sock withError:(NSError *)error {
        NSLog(@"关闭");
    }

    相关文章

      网友评论

        本文标题:使用GCDAsyncUdpSocket进行局域网广播寻址

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