局域网内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结构体自己画的图解如下:
创建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(@"关闭");
}