iOS 上的 GCDAsyncUdpSocket 缺少多播数据报 [英] GCDAsyncUdpSocket on iOS missing multicasted datagrams

查看:23
本文介绍了iOS 上的 GCDAsyncUdpSocket 缺少多播数据报的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我在网络上有一台设备通过 UDP 多播一个非常小的文件.我正在开发的 iOS 应用程序负责读取这些数据包,我选择使用 GCDAsyncUdpSocket 来执行此操作.该文件每半秒发送一次,但是我几乎没有收到它(大约每 3-10 秒接收一次).

I have a device on the network that is multicasting a very small file via UDP. The iOS app I am developing is responsible for reading these packets and I have chosen to use GCDAsyncUdpSocket to do so. The file is sent every half second, however I am not receiving it nearly that often (only receiving about every 3-10 seconds).

认为这可能是设备的问题,我开始使用 Wireshark 监控流量.这似乎反映了我在应用程序中看到的内容,直到我在 Wireshark 中启用监控模式",此时每个 UDP 数据包都被捕获.此外,iOS 模拟器开始接收所有丢失的数据包,因为它与我正在开发的 Mac 共享 NIC.

Thinking that it may be an issue with the device, I began monitoring the traffic with Wireshark. This appeared to reflect what I was seeing in my app until I enabled "Monitor Mode" in Wireshark, at which point every UDP packet was being captured. In addition, the iOS simulator began receiving all of the missing packets since it shares the NIC with the Mac I am developing on.

有没有办法在 iOS 设备上启用监控模式"或我缺少的东西可以让丢失的数据包进入?我还看到 GCDAsyncUdpSocket 中有一个 readStream 方法.也许我需要使用它而不是 beginReceiving?虽然如果是这样的话,我不知道如何在 Objective-C 中设置流.

Is there a way to enable "Monitor Mode" on an iOS device or something I am missing that would allow the missing packets to come in? I also see that there is a readStream method in GCDAsyncUdpSocket. Perhaps I need to use this instead of beginReceiving? Though I do not know how to set up streams in Objective-C if that is the case.

这是我现在的测试代码:

Here is my test code as it is now:

- (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);
    }
}

<小时>

为将来来这里的任何人提供解决方案:

根据 ilmiacs 的回答,我能够通过 ping 目标 iOS 设备显着减少丢失数据包的数量.使用 Mac,我在终端中运行了它 -

Based on ilmiacs's answer, I was able to significantly reduce the number of missing packets by pinging the target iOS device. Using a Mac, I ran this in the terminal -

sudo ping -i 0.2 -s 4 <Target IP>

现在我让它在 Mac 上运行 ping iOS 设备,我将研究 Apple 的 iOS ping 示例,看看是否可以让设备 ping 自身以刺激其自己的无线适配器 (127.0.0.1).

Now that I have it running with a Mac pinging the iOS device, I am going to look into Apple's iOS ping examples and see if I can have the device ping itself to stimulate its own wireless adapter (127.0.0.1).

推荐答案

通过我为 iOS 设备开发网络应用程序的工作,我发现他们的网络适配器有两种不同的模式,我们称它们为主动和被动.我没有找到任何关于此的文档.以下是我的发现:

Through my work on networking apps for iOS devices I have revealed that their network adapters have two different modes, let's call them active and passive. I did not manage to find any documentation on this. Here are my findings:

  1. 只要处于活动模式,适配器就会非常灵敏.我的响应时间为 3-5 毫秒.

  1. As long as in active mode, the adapter is quite responsive. I have response times of 3-5ms.

在闲置一段时间后,iOS 的网络适配器从主动模式变为被动模式.发生这种情况的时间取决于实际的设备型号.第三代 iPad 大约是 200 毫秒.对于 iPhone 4,它更像是 50 毫秒.

After some time of inactivity, the network adapter of the iOS falls from active to passive mode. The time for this to happen, depends on the actual device model. 3rd gen iPad it is around 200ms. For the iPhone 4 its more like 50ms.

ping 请求或 TCP 数据包会将适配器从被动模式移动到主动模式.这可能需要 50 毫秒到 800 毫秒不等的时间,平均约为 200 毫秒.

A ping request or a TCP packet will move the adapter from passive to active mode. This may take anything from 50ms to 800ms, with an average of around 200ms.

通过发出 ping 命令可以完全重现此行为.例如

This behavior is completely reproducible by issuing ping commands. E.g.

ping -i 0.2 <ios-device-ip>

将 ping 间隔设置为 200 毫秒,并使我的 iPad 网络适配器保持活动状态.

sets the ping interval to 200ms and keeps my iPads network adapter in the active state.

如果适配器(通常)在被动模式下忽略 UDP 数据包,则此行为与您的观察完全一致.Wireshark 活动可能会使其处于活动模式,因此它会获取 UDP.

This behavior is completely consistent with your observations, if the adapter (more often than not) ignores UDP packets when in passive mode. The wireshark activity probably keeps it in active mode so then it would get the UDPs.

检查 ping 技巧是否有帮助.

Check out whether the ping trick helps.

可以通过打开和连接设备本身的两个套接字并定期向自己发送数据包来使 iDevice 的网络适配器保持活动状态.这将引入一些最小的开销.

One probably could keep the network adapter of the iDevice in the active state by opening and connecting two sockets on the device itself and regularly sending itself packets. This would introduce some minimal overhead.

至于为什么苹果决定实现这样一个功能,我只能猜测.但是,保持适配器处于活动状态可能会消耗足够的电池电量来使这种设计选择合法化.

As to why apple decided to implement such a feature, I can only speculate about. But probably keeping the adapter active costs sufficient battery power to legitimate such a design choice.

希望这会有所帮助.

这篇关于iOS 上的 GCDAsyncUdpSocket 缺少多播数据报的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆