iOS 局域网搜索可以使用两种方式。第一种方式局域网广播方式、此方式一般在3秒内就会相应。第二种方式也是比较笨拙的方式通过ping方式、这种方式一般是在硬件本身并不支持广播功能。此方法弊端:搜索时间长。推荐:可以有广播功能的使用第一种方式、没有广播功能和局域网内设备相对较少以及是连接手机wifi热点的情况。
第一种方式 广播:
推荐使用第三方GCDAsynSoket 代码如下:
@interface SearchCenter()<GCDAsyncUdpSocketDelegate> //@property(nonatomic, strong) NSMutableArray *arpTableList; @property(nonatomic, strong) GCDAsyncUdpSocket *gcdAsyncUdpSocket; //广播定时器 @property(nonatomic, strong) NSTimer *broadcastTimer; @end -(GCDAsyncUdpSocket *)gcdAsyncUdpSocket { if (!_gcdAsyncUdpSocket) { //: CameraBroadCastResponsePort 为设备回调消息过来的监听端口 _gcdAsyncUdpSocket = [[GCDAsyncUdpSocket alloc]initWithDelegate:self delegateQueue:dispatch_get_main_queue()]; NSError *err = nil; [_gcdAsyncUdpSocket enableBroadcast:YES error:&err]; [_gcdAsyncUdpSocket bindToPort: CameraBroadCastResponsePort error:&err]; [_gcdAsyncUdpSocket beginReceiving:&err]; } return _gcdAsyncUdpSocket; } -(NSTimer *)broadcastTimer { if (!_broadcastTimer) { _broadcastTimer = [NSTimer scheduledTimerWithTimeInterval:1.0 target:self selector:@selector(broadcastAction) userInfo:nil repeats:YES]; [_broadcastTimer setFireDate:[NSDate distantFuture]]; } return _broadcastTimer; } #pragma mark 广播方式搜索 -(void)startUdpBroadcastAddress:(NSString *)broadcastAddress { _broadcastAddress = broadcastAddress; _currentSearchStatus = KPXSearchStatusSearching; _searchTimes = 0; [self.deviceList removeAllObjects]; NSLog(@"开始udp广播"); [self.broadcastTimer setFireDate:[NSDate distantPast]]; } //广播定时器 -(void)broadcastAction { //_broadcastAddress 为广播地址(该地址获取方式请下载代码查看) CameraBroadCastMonitorPort为硬件设备监听端口 NSData *data = [ CameraUdpBroadCastCmd dataUsingEncoding:NSUTF8StringEncoding]; [self.gcdAsyncUdpSocket sendData:data toHost:_broadcastAddress port: CameraBroadCastMonitorPort withTimeout:-1 tag:0]; } if (_searchTimes >= 30) { CameraManager *camraManager = [ CameraManager shareManager]; [camraManager stopSearch]; } } #pragma mark GCDAsyncUdpSocketDelegate - (void)udpSocket:(GCDAsyncUdpSocket *)sock didSendDataWithTag:(long)tag { NSLog(@"udp发送数据"); } - (void)udpSocket:(GCDAsyncUdpSocket *)sock didNotSendDataWithTag:(long)tag dueToError:(NSError * _Nullable)error { NSLog(@"udp发送出错"); } - (void)udpSocket:(GCDAsyncUdpSocket *)sock didReceiveData:(NSData *)data fromAddress:(NSData *)address withFilterContext:(nullable id)filterContext { NSString *resposeString = [[NSString alloc]initWithData:data encoding:NSUTF8StringEncoding]; // NSLog(@"resposeString=%@",resposeString); if ([resposeString containsString:@"ip"]) { NSString *deviceIp = [GCDAsyncUdpSocket hostFromAddress:address]; // uint16_t port = [GCDAsyncUdpSocket portFromAddress:address]; NSDictionary *dict =[NSDictionary dictionaryWithObjectsAndKeys:deviceIp,@"ipAdress", nil]; if (![self.deviceList containsObject:dict]) { [self.deviceList addObject:dict]; NSLog(@"发现摄像头:%@待验证",dict); [self searchPasue]; if (self.delegete && [self.delegete respondsToSelector:@selector(searchDeviceListDidChange)]) { [self.delegete searchDeviceListDidChange]; } }else{ //已经添加到设备列表 NSInteger index = [self.deviceList indexOfObject:dict]; [self.deviceList exchangeObjectAtIndex:index withObjectAtIndex:self.deviceList.count-1]; //判断http服务器是否响应已经确认为摄像头 __block BOOL isExist = NO; CameraManager *camraManager = [ CameraManager shareManager]; [camraManager.onlineCameras enumerateObjectsUsingBlock:^(id _Nonnull obj, NSUInteger idx, BOOL * _Nonnull stop) { Camera *camra = obj; if ([camra.camerIp isEqualToString:deviceIp]) { isExist = YES; *stop = YES; } }]; if (isExist == NO && _currentSearchStatus == KPXSearchStatusSearching) { [self searchPasue]; //摄像头http服务首次未响应待验证 NSLog(@"http服务未响应、正在重试...."); if (self.delegete && [self.delegete respondsToSelector:@selector(searchDeviceListDidChange)]) { [self.delegete searchDeviceListDidChange]; } } } } } - (void)udpSocketDidClose:(GCDAsyncUdpSocket *)sock withError:(NSError * _Nullable)error { NSLog(@"udpSocketDidClose"); } 第二种方式ping 1.首先借助苹果官方提供的SimplePing. 代码如下: .h文件如下 #import <Foundation/Foundation.h> @interface XplorePing : NSObject //初始化并开始ping +( XplorePing *)createPingHostName:(NSString *)hostName finishAction:(void (^)(BOOL isOK))finishAction; //开始ping -(void)startPingHostName:(NSString *)hostName finishAction:(void (^)(BOOL isOK))finishAction; @end .m文件如下 #import "SimplePing.h" @interface XplorePing()<SimplePingDelegate> @property(nonatomic, strong) SimplePing *pinger; @end @implementation XplorePing{ int _times; NSTimer *_timer; BOOL _pingSuccess; void (^_pingFinishAction)(BOOL); } -(void)dealloc { // NSLog(@"被释放了 Ping"); } +( XplorePing *)createPingHostName:(NSString *)hostName finishAction:(void (^)(BOOL isOK))finishAction { XplorePing *ping = [[ XplorePing alloc]init]; [ping startPingHostName:hostName finishAction:finishAction]; return ping; } -(void)startPingHostName:(NSString *)hostName finishAction:(void (^)(BOOL isOK))finishAction { SimplePing *pinger = [[SimplePing alloc] initWithHostName:hostName]; self.pinger = pinger; pinger.delegate = self; pinger.addressStyle = SimplePingAddressStyleAny;//ipv4和ipv6环境 //初始化基本 _pingFinishAction = finishAction; _pingSuccess = NO; //清零 _times = 0; _timer = [NSTimer scheduledTimerWithTimeInterval:0.4 target:self selector:@selector(start) userInfo:nil repeats:YES]; [_timer fire]; [[NSRunLoop currentRunLoop]run]; } -(void)start { [self.pinger stop]; [self.pinger start]; _times ++; if (_times>=5) { //销毁 [_timer invalidate]; _timer = nil; [self.pinger stop]; //回调 if (_pingFinishAction) { _pingFinishAction(_pingSuccess); } return;//必须的 } } /** * start成功,也就是准备工作做完后的回调 */ - (void)simplePing:(SimplePing *)pinger didStartWithAddress:(NSData *)address { // NSLog(@"开始ping"); // 发送测试报文数据 [self.pinger sendPingWithData:nil]; } - (void)simplePing:(SimplePing *)pinger didFailWithError:(NSError *)error { NSLog(@"didFailWithError"); [self.pinger stop]; } // 发送测试报文成功的回调方法 - (void)simplePing:(SimplePing *)pinger didSendPacket:(NSData *)packet sequenceNumber:(uint16_t)sequenceNumber { NSLog(@"#%u sent", sequenceNumber); } //发送测试报文失败的回调方法 - (void)simplePing:(SimplePing *)pinger didFailToSendPacket:(NSData *)packet sequenceNumber:(uint16_t)sequenceNumber error:(NSError *)error { NSLog(@"#%u send failed: %@", sequenceNumber, error); } // 接收到ping的地址所返回的数据报文回调方法 - (void)simplePing:(SimplePing *)pinger didReceivePingResponsePacket:(NSData *)packet sequenceNumber:(uint16_t)sequenceNumber { NSLog(@"#%u received, size=%zu", sequenceNumber, packet.length); //标记成功 _pingSuccess = YES; [_timer invalidate]; _timer = nil; [self.pinger stop]; if (_pingFinishAction) { _pingFinishAction(_pingSuccess); } } - (void)simplePing:(SimplePing *)pinger didReceiveUnexpectedPacket:(NSData *)packet { NSLog(@"#%s",__func__); } @end
广播地址获取以及源码获取:https://files.cnblogs.com/files/ChangeStrong/WifiManager.zip 有什么不明白的请留言或者加Q:491337430