首页
学习
活动
专区
工具
TVP
发布
社区首页 >问答首页 >iPhone数据使用情况跟踪/监控

iPhone数据使用情况跟踪/监控
EN

Stack Overflow用户
提问于 2011-10-31 01:56:14
回答 7查看 57.1K关注 0票数 139

我已经搜索了这个主题,但发现很少有帮助的细节。有了这些细节,我试着编写一些代码,如下所示。

注意:在将本文标记为重复之前,请将此帖子中共享的详细信息与其他帖子进行比较,而不仅仅是按主题进行比较。

代码语言:javascript
复制
- (NSArray *)getDataCountersForType:(int)type {
    BOOL success;
    struct ifaddrs *addrs = nil;
    const struct ifaddrs *cursor = nil;
    const struct sockaddr_dl *dlAddr = nil;
    const struct if_data *networkStatisc = nil; 

    int dataSent = 0;
    int dataReceived = 0;

    success = getifaddrs(&addrs) == 0;
    if (success) {
        cursor = addrs;
        while (cursor != NULL) {
            if (cursor->ifa_addr->sa_family == AF_LINK) {
                dlAddr = (const struct sockaddr_dl *) cursor->ifa_addr;
                networkStatisc = (const struct if_data *) cursor->ifa_data;

                if (type == WiFi) {
                    dataSent += networkStatisc->ifi_opackets;
                    dataReceived += networkStatisc->ifi_ipackets;   
                }
                else if (type == WWAN) {
                    dataSent += networkStatisc->ifi_obytes;
                    dataReceived += networkStatisc->ifi_ibytes; 
                }
            }
            cursor = cursor->ifa_next;
        }
        freeifaddrs(addrs);
    }       
    return [NSArray arrayWithObjects:[NSNumber numberWithInt:dataSent], [NSNumber numberWithInt:dataReceived], nil];    
}

此代码收集iPhone设备(而不仅仅是我的应用程序)的互联网使用信息。

现在,如果我通过WiFi或3G使用互联网,我只能获得ifi_obytes (发送)和ifi_ibytes (接收)格式的数据(字节),但我认为我应该获得ifi_opacketsifi_ipackets格式的WiFi使用情况。

我还想补充说,如果我连接到WiFi网络,但没有使用互联网,我仍然可以获得ifi_obytesifi_ibytes的附加值。

也许我在实现或理解上是错误的。需要有人来帮我。

编辑:我尝试了AF_INET而不是AF_LINK (sockaddr_in而不是sockaddr_dl)。这会使应用程序崩溃。

EN

回答 7

Stack Overflow用户

回答已采纳

发布于 2011-11-05 02:21:34

问题是pdp_ip0是其中的一个接口,所有的pdpXXX都是专用于不同功能的WWAN接口,语音信箱,通用网络接口。

我在Apple论坛上读到:操作系统不会以进程为单位保存网络统计数据。因此,这个问题没有确切的解决方案。但是,您可以获取每个网络接口的网络统计信息。

通常,en0是您的Wi-Fi接口,pdp_ip0是您的WWAN接口。

没有好的方法来获取信息wifi/蜂窝网络数据,因为,特别是日期-时间!

数据统计(ifa_data->ifi_obytesifa_data->ifi_ibytes)存储上次设备重新启动时的数据。

我不知道为什么,但是ifi_opacketsifi_ipackets是为lo0 (我想它的主界面)而显示的。

是。然后设备通过WiFi连接,而不使用互联网,if_iobytes值仍然会出现,因为这种方法提供了网络字节交换,而不仅仅是互联网。

代码语言:javascript
复制
#include <net/if.h>
#include <ifaddrs.h>

static NSString *const DataCounterKeyWWANSent = @"WWANSent";
static NSString *const DataCounterKeyWWANReceived = @"WWANReceived";
static NSString *const DataCounterKeyWiFiSent = @"WiFiSent";
static NSString *const DataCounterKeyWiFiReceived = @"WiFiReceived";

NSDictionary *DataCounters()
{
    struct ifaddrs *addrs;
    const struct ifaddrs *cursor;

    u_int32_t WiFiSent = 0;
    u_int32_t WiFiReceived = 0;
    u_int32_t WWANSent = 0;
    u_int32_t WWANReceived = 0;

    if (getifaddrs(&addrs) == 0)
    {
        cursor = addrs;
        while (cursor != NULL)
        {
            if (cursor->ifa_addr->sa_family == AF_LINK)
            {
#ifdef DEBUG
                const struct if_data *ifa_data = (struct if_data *)cursor->ifa_data;
                if (ifa_data != NULL)
                {
                    NSLog(@"Interface name %s: sent %tu received %tu",cursor->ifa_name,ifa_data->ifi_obytes,ifa_data->ifi_ibytes);
                }
#endif

                // name of interfaces:
                // en0 is WiFi
                // pdp_ip0 is WWAN
                NSString *name = @(cursor->ifa_name);
                if ([name hasPrefix:@"en"])
                {
                    const struct if_data *ifa_data = (struct if_data *)cursor->ifa_data;
                    if (ifa_data != NULL)
                    {
                        WiFiSent += ifa_data->ifi_obytes;
                        WiFiReceived += ifa_data->ifi_ibytes;
                    }
                }

                if ([name hasPrefix:@"pdp_ip"])
                {
                    const struct if_data *ifa_data = (struct if_data *)cursor->ifa_data;
                    if (ifa_data != NULL)
                    {
                        WWANSent += ifa_data->ifi_obytes;
                        WWANReceived += ifa_data->ifi_ibytes;
                    }
                }
            }

            cursor = cursor->ifa_next;
        }

        freeifaddrs(addrs);
    }

    return @{DataCounterKeyWiFiSent : @(WiFiSent),
             DataCounterKeyWiFiReceived : @(WiFiReceived),
             DataCounterKeyWWANSent : @(WWANSent),
             DataCounterKeyWWANReceived : @(WWANReceived)};
}

改进了对复制/粘贴的支持!

票数 178
EN

Stack Overflow用户

发布于 2012-05-23 04:10:51

重要的是要理解,这些计数器是自设备上次启动以来提供的

因此,为了有效地利用它们,您应该将每个样本与设备的正常运行时间一起使用(您可以使用mach_absolute_time() -有关更多信息,请参阅this )

一旦你有了计数器样本+正常运行时间,你就可以有更好的启发式数据使用……

票数 17
EN

Stack Overflow用户

发布于 2015-06-10 03:41:15

要添加到可接受的答案中,重要的是要认识到接口显示的数据量在每次4 GB后溢出并在0重新启动,特别是当您使用此代码计算两个读数之间的差值时。这是因为ifi_obytesifi_ibytesuint_32,它们的最大值是4294967295

另外,我建议对包含发送和接收的数据的变量使用unsigned int。常规int的最大值是无符号整数的一半,因此在添加ifi_obytes时,可能会导致溢出。

代码语言:javascript
复制
unsigned int sent = 0;
sent += networkStatisc->ifi_obytes;
票数 14
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/7946699

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档