iOS上的GCDAsyncUdpSocket丢失了多播数据报
我有一个networking上的设备,通过UDP组播一个非常小的文件。 我正在开发的iOS应用程序负责读取这些数据包,我select使用GCDAsyncUdpSocket来做到这一点。 该文件每半秒发送一次,但我几乎没有收到它(往往每3-10秒接收一次)。
考虑到这可能是设备的问题,我开始使用Wireshark监控stream量。 这似乎反映了我在应用程序中看到的内容,直到我在Wireshark中启用“Monitor Mode”为止,此时每个UDP数据包都被捕获。 此外,iOS模拟器开始接收所有丢失的数据包,因为它与我正在开发的Mac共享网卡。
有没有办法在iOS设备上启用“监视器模式”,或者我缺less一些可以丢失数据包的东西? 我也看到在GCDAsyncUdpSocket中有一个readStream方法。 也许我需要使用这个而不是beginReceiving? 尽pipe如此,我不知道如何在Objective-C中设置stream。
这是我现在的testing代码:
- (void)viewDidLoad { [super viewDidLoad]; // Do any additional setup after loading the view, typically from a nib. NSLog(@"View Loaded"); [self setupSocket]; } - (void)setupSocket { udpSocket = [[GCDAsyncUdpSocket alloc] initWithDelegate:self delegateQueue:dispatch_get_main_queue()]; NSError *error = nil; if (![udpSocket bindToPort:5555 error:&error]) { NSLog(@"Error binding to port: %@", error); return; } if(![udpSocket joinMulticastGroup:@"226.1.1.1" error:&error]){ NSLog(@"Error connecting to multicast group: %@", error); return; } if (![udpSocket beginReceiving:&error]) { NSLog(@"Error receiving: %@", error); return; } NSLog(@"Socket Ready"); } - (void)udpSocket:(GCDAsyncUdpSocket *)sock didReceiveData:(NSData *)data fromAddress:(NSData *)address withFilterContext:(id)filterContext { NSString *msg = [[NSString alloc] initWithData:data encoding:NSUTF8StringEncoding]; if (msg) { NSLog(@"RCV: %@", msg); } else { NSString *host = nil; uint16_t port = 0; [GCDAsyncUdpSocket getHost:&host port:&port fromAddress:address]; NSLog(@"Unknown message from : %@:%hu", host, port); } }
任何人在未来来到这里的解决scheme:
基于ilmiacs的回答,我能够通过ping目标iOS设备来显着减less丢失数据包的数量。 使用Mac,我在terminal上运行了这个 –
sudo ping -i 0.2 -s 4 <Target IP>
现在我已经用苹果电脑对iOS设备进行了ping操作,我将看看苹果公司的iOS ping示例,看看是否可以让设备ping自己来激发自己的无线适配器(127.0.0.1)。
通过我的iOS设备networking应用工作,我发现他们的networking适配器有两种不同的模式,我们称之为主动和被动模式。 我没有设法find任何文件。 这是我的发现:
-
只要在主动模式下,适配器是相当敏感的。 我有3-5ms的响应时间。
-
经过一段时间的不活动之后,iOS的networking适配器从主动模式变为被动模式。 发生这种情况的时间取决于实际的设备型号。 第三代iPad是200毫秒左右。 对于iPhone 4来说,它更像是50ms。
-
ping请求或TCP数据包将使适配器从被动模式移动到主动模式。 这可能需要从50毫秒到800毫秒,平均约200毫秒。
通过发出ping命令可以完全重现此行为。 例如
ping -i 0.2 <ios-device-ip>
将ping间隔设置为200毫秒,并使我的iPadnetworking适配器保持活动状态。
这种行为与您的观察完全一致,如果适配器(通常比较less)在被动模式下忽略UDP数据包。 wireshark活动可能会保持它在活动模式,这样就可以得到UDP。
看看ping技巧是否有帮助。
通过在设备上打开和连接两个sockets并定期发送自己的数据包,可能会使iDevice的networking适配器处于活动状态。 这会引入一些最小的开销。
至于为什么苹果决定实施这样的function,我只能推测一下。 但可能保持适配器活动成本足够的电池电力来合法这样的deviseselect。
希望这可以帮助。
我遇到过同样的问题。
开始networking活动指标为我解决了这个问题:
UIApplication* app = [UIApplication sharedApplication]; app.networkActivityIndicatorVisible = YES;
如果要在iOS设备上查看数据包,可以将iOS设备连接到Mac,然后使用shell命令rvictl挂载WiFi适配器。 然后,您可以使用wireshark,tcpdump等来监控您的iOS设备上802.11接口的stream量。
至于3到7秒内没有接收数据 – 很可能您的设备正在进入省电模式(IEEE PSM),这是一项802.11function,基本上使无线NIC处于睡眠状态。
PSM模式可能会导致设备性能下降 – 尤其是在您每1/2秒发生一次周期性突发数据的情况下。 您的定期ping是唤醒NIC。