iPhone数据使用跟踪/监控

Sah*_*nna 135 sockets iphone ios

我搜索了这个主题,但发现很少有帮助的细节.有了这些细节,我试着按如下方式编写一些代码.

注意:请将此帖中分享的详细信息与其他帖子进行比较,然后再将其标记为DUPLICATE,而不仅仅是主题.

- (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];    
}
Run Code Online (Sandbox Code Playgroud)

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

现在,如果我通过WiFi或通过3G使用互联网,我只能在ifi_obytes(已发送)和ifi_ibytes(已接收)中获取数据(字节),但我认为我应该在ifi_opackets和中使用WiFi ifi_ipackets.

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

可能是我在实施或理解上错了.需要有人帮助我.


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

use*_*705 173

问题是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值仍然来,因为这种方法提供网络字节交换而不仅仅是互联网.

#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)};
}
Run Code Online (Sandbox Code Playgroud)

改进的复制/粘贴支持!

  • 您需要导入以下库:#include <arpa/inet.h> #include <net/if.h> #include <ifaddrs.h> #include <net/if_dl.h> (20认同)
  • 是否可以使用此代码跟踪每个iOS应用程序的数据流量? (9认同)
  • 有没有人想出如何获得每个应用程序的数据?请分享代码:) (4认同)
  • 多谢。这段代码创造了奇迹。也感谢您解释这些内容。 (2认同)
  • @Mat:我为企业客户设计的解决方案,并未部署在AppStore上. (2认同)
  • 我们可以找出每个应用程序的数据使用情况吗?@fvisticot 你有没有得到任何解决方案,请帮助我。 (2认同)
  • 是否可以跟踪单个应用程序的数据传输使用情况? (2认同)

小智 16

重要的是要了解这些计数器是在设备上次启动后提供的.

因此,为了有效地使用它们,您应该为每个样本提供设备的正常运行时间(您可以使用mach_absolute_time()- 请参阅信息以获取更多信息)

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


Jim*_*109 12

要添加到接受的答案,重要的是要意识到接口显示的数据量会溢出并在0每次之后重新启动4 GB,尤其是如果您使用此代码来计算两个读数之间的差异.这是因为ifi_obytesifi_ibytesuint_32和他们的最大值为4294967295.

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

unsigned int sent = 0;
sent += networkStatisc->ifi_obytes;
Run Code Online (Sandbox Code Playgroud)


Adn*_*tab 5

已接受答案的快速版本。我还将代码分解成更小的单元。

struct DataUsageInfo {
    var wifiReceived: UInt32 = 0
    var wifiSent: UInt32 = 0
    var wirelessWanDataReceived: UInt32 = 0
    var wirelessWanDataSent: UInt32 = 0

    mutating func updateInfoByAdding(info: DataUsageInfo) {
        wifiSent += info.wifiSent
        wifiReceived += info.wifiReceived
        wirelessWanDataSent += info.wirelessWanDataSent
        wirelessWanDataReceived += info.wirelessWanDataReceived
    }
}

class DataUsage {

    private static let wwanInterfacePrefix = "pdp_ip"
    private static let wifiInterfacePrefix = "en"

    class func getDataUsage() -> DataUsageInfo {
        var interfaceAddresses: UnsafeMutablePointer<ifaddrs> = nil
        var dataUsageInfo = DataUsageInfo()

        guard getifaddrs(&interfaceAddresses) == 0 else { return dataUsageInfo }

        var pointer = interfaceAddresses
        while pointer != nil {
            guard let info = getDataUsageInfo(from: pointer) else {
                pointer = pointer.memory.ifa_next
                continue
            }
            dataUsageInfo.updateInfoByAdding(info)
            pointer = pointer.memory.ifa_next
        }

        freeifaddrs(interfaceAddresses)

        return dataUsageInfo
    }

    private class func getDataUsageInfo(from infoPointer: UnsafeMutablePointer<ifaddrs>) -> DataUsageInfo? {
        let pointer = infoPointer

        let name: String! = String.fromCString(infoPointer.memory.ifa_name)

        let addr = pointer.memory.ifa_addr.memory
        guard addr.sa_family == UInt8(AF_LINK) else { return nil }

        return dataUsageInfo(from: pointer, name: name)
    }

    private class func dataUsageInfo(from pointer: UnsafeMutablePointer<ifaddrs>, name: String) -> DataUsageInfo {
        var networkData: UnsafeMutablePointer<if_data> = nil
        var dataUsageInfo = DataUsageInfo()

        if name.hasPrefix(wifiInterfacePrefix) {
            networkData = unsafeBitCast(pointer.memory.ifa_data, UnsafeMutablePointer<if_data>.self)
            dataUsageInfo.wifiSent += networkData.memory.ifi_obytes
            dataUsageInfo.wifiReceived += networkData.memory.ifi_ibytes
        } else if name.hasPrefix(wwanInterfacePrefix) {
            networkData = unsafeBitCast(pointer.memory.ifa_data, UnsafeMutablePointer<if_data>.self)
            dataUsageInfo.wirelessWanDataSent += networkData.memory.ifi_obytes
            dataUsageInfo.wirelessWanDataReceived += networkData.memory.ifi_ibytes
        }

        return dataUsageInfo
    }
}
Run Code Online (Sandbox Code Playgroud)