By Sahil Khanna


2011-10-30 17:56:13 8 Comments

I've searched over this topic but found very few details which were helpful. With these details I've tried to cook some code as follows.

Note: Please compare the details shared in this post with other posts before marking this as DUPLICATE, and not just by the subject.

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

This code collects information of internet usage of an iPhone device (and not my application alone).

Now, if I use internet through WiFi or through 3G, I get the the data (bytes) only in ifi_obytes (sent) and ifi_ibytes (received) but I think I should get WiFi usage in ifi_opackets and ifi_ipackets.

Also wanted to add that if I'm connected to a WiFi network, but am not using internet, I still get value added to ifi_obytes and ifi_ibytes.

May be I'm wrong in the implementation or understanding. Need someone to help me out.


Edit: Instead of AF_LINK I tried AF_INET (sockaddr_in instead of sockaddr_dl). This crashes the application.

6 comments

@user982705 2011-11-04 18:21:33

The thing is that pdp_ip0 is one of interfaces, all pdpXXX are WWAN interfaces dedicated to different functions, voicemail, general networking interface.

i read in apple forum that : The OS does not keep network statistics on a process-by-process basis. As such, there's no exact solution to this problem. You can, however, get network statistics for each network interface.

In general en0 is your Wi-Fi interface and pdp_ip0 is your WWAN interface.

There is no good way to get information wifi/cellular network data since, particular date-time!

data statistic (ifa_data->ifi_obytes and ifa_data->ifi_ibytes) are stored from previous device reboot.

i don't know why, but ifi_opackets and ifi_ipackets are shown just for lo0 (i think its main interface ).

yes. Then device is connected via WiFi and doesn't use internet if_iobytes values still come because this method provides network bytes exchanges and not just internet .

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

Improved copy/paste support !

@Sahil Khanna 2011-11-05 14:10:03

Thanks a lot. This code worked wonders. Also thanks for explaining the stuff.

@Edig 2012-02-04 06:52:12

how do i call this code?

@user982705 2012-02-11 21:51:53

You need to import this libraries: #include <arpa/inet.h> #include <net/if.h> #include <ifaddrs.h> #include <net/if_dl.h>

@elsurudo 2012-03-07 12:38:29

Do I understand correctly that the data usage counters get reset on device reboot?

@user982705 2012-03-11 11:35:42

Yes. Usage counters are equal to zero after device reboot !

@fvisticot 2012-04-30 15:36:24

Is it possible with this code to track data traffic per iOS application ?

@user982705 2012-05-10 10:29:30

Yes. But not exact, data statistic are stored from previos device reboot.

@Mat 2012-05-19 23:42:46

@Sahil Could i know if you have used this code in some AppStore apps?

@Sahil Khanna 2012-05-21 04:48:05

@Mat: The solution I've designed if for enterprise clients and is not deployed on the AppStore.

@Herz Rod 2012-07-20 14:33:34

I would like to know why the values doesn't match the ones provided by the system (I've restored statistics and rebooted device)

@iOmi 2013-01-17 06:08:25

Does this code works for iPhone?

@user982705 2013-01-18 17:49:36

Yes. This code still works! :) I copied it from this post and build it again with no problems.

@Shashank Kulshrestha 2013-05-21 12:14:28

Can we find out data usage by each application? @fvisticot did you get any solution please help me.

@guptron 2013-05-29 20:25:15

@Sahil Are you aware of any objection Apple if the app needed to go through the approval process?

@Sahil Khanna 2013-05-30 08:14:27

@SKG: The solution I've designed is for enterprise clients and is not deployed on the AppStore. However I dont see anything in the code that violates Apple's policy. All APIs used are public. I suggest you upload the app to the AppStore and share the results.

@Vipin Vijay 2013-06-05 12:58:30

How to get network bandwidth using this code

@Eddy 2014-05-23 15:12:11

Is this public API? In other words would the app store accept an app that uses this?

@Nilesh Agrawal 2014-07-14 22:07:33

What about finding the same on cellular network. without wifi !

@Eddy 2014-09-25 11:19:35

I'm using this code in my app and it seems like for some users it's returning negative values. How can that be?

@Bob de Graaf 2015-01-27 11:10:08

Has anybody figured out how to get the data per app? Share the code please :)

@Shaggy D 2015-06-16 11:28:07

@user982705 how did you handle the reset-on-reboot condition for monitoring data usage?

@Alen Alexander 2015-07-27 08:25:49

Does there exists any solution to find the DATA USAGE PER APP ???

@Raphael 2015-08-11 16:02:36

@Eddy, try replacing the type "int" with "unsigned int". You seem to experience an overflow problem which results in negative values.

@user982705 2015-08-12 08:22:32

I have rewritten code a little bit now it can be copied and pasted without additional pains

@Durai Amuthan.H 2016-02-18 13:45:56

is the above code snippet for a application or device ?

@Maneesh Sharma 2016-08-29 10:04:52

@user982705 Can you tell me the minimum deployment target to implement this code ? will it support iOS 6 ?

@Mr.G 2016-12-02 05:04:07

Thanks for sharing this , and with this i can get the network stat on each interface , But is it possible for me to take network usage based on app ???

@Maneesh Sharma 2017-02-27 06:39:14

@user982705 , Is it possible for us to access it from ifa_data64 structure ? since it returns the value as u_int64_t as per the if_var.h file . Can you please refer and tell ?

@Harsh K 2017-03-04 18:43:13

Can I Know the time duration the wifi was used and which wifi it was connected to?

@Kuldeep 2017-05-22 12:14:48

@user982705 how can I track data usage application wise?

@techsMex 2017-09-15 17:41:06

The comments in the code says "en0 is WiFi" but the code sums bytes from all if_data structs starting with "en". On my device I have en0, en1, en2... Should it just be en0?

@Sharavanakumaar Murugesan 2017-11-01 14:22:51

Is it possible to track single application data transmission usage?

@Slavcho 2018-10-03 09:38:22

The bytes for WWAN represents the amount of data since last reboot? How can I get the data usage for custom period of time?

@dede.exe 2018-01-12 19:03:05

A new version about based on previous versions, but adapted for Swift4 and Xcode 9

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!.pointee.ifa_next
                continue
            }
            dataUsageInfo.updateInfoByAdding(info: info)
            pointer = pointer!.pointee.ifa_next
        }

        freeifaddrs(interfaceAddresses)

        return dataUsageInfo
    }

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

        let name: String! = String(cString: infoPointer.pointee.ifa_name)
        let addr = pointer.pointee.ifa_addr.pointee
        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.pointee.ifa_data, to: UnsafeMutablePointer<if_data>.self)
            dataUsageInfo.wifiSent += networkData?.pointee.ifi_obytes ?? 0
            dataUsageInfo.wifiReceived += networkData?.pointee.ifi_ibytes ?? 0
        } else if name.hasPrefix(wwanInterfacePrefix) {
            networkData = unsafeBitCast(pointer.pointee.ifa_data, to: UnsafeMutablePointer<if_data>.self)
            dataUsageInfo.wirelessWanDataSent += networkData?.pointee.ifi_obytes ?? 0
            dataUsageInfo.wirelessWanDataReceived += networkData?.pointee.ifi_ibytes ?? 0
        }

        return dataUsageInfo
    }
}

@Maksim Kniazev 2018-05-08 00:20:40

does it show for each app or the actual app where it's used?

@dede.exe 2018-05-08 23:34:55

It's the global usage... It's not separated by app.

@Slavcho 2018-10-04 13:33:54

And the value is from the last reboot. No way of getting for the past/current month?

@dede.exe 2018-10-04 13:39:02

@Slavcho. Until this post date it was not possible. I still didn't do a new research about it after iOS12. I recommend you to accumulate ir in some place to recovery it after.

@Jonghee Park 2017-05-11 13:30:45

I fixed above source code to Swift3 version

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 ifaddr: UnsafeMutablePointer<ifaddrs>?
        var dataUsageInfo = DataUsageInfo()

        guard getifaddrs(&ifaddr) == 0 else { return dataUsageInfo }
        while let addr = ifaddr {
            guard let info = getDataUsageInfo(from: addr) else {
                ifaddr = addr.pointee.ifa_next
                continue
            }
            dataUsageInfo.updateInfoByAdding(info)
            ifaddr = addr.pointee.ifa_next
        }

        freeifaddrs(ifaddr)

        return dataUsageInfo
    }

    private class func getDataUsageInfo(from infoPointer: UnsafeMutablePointer<ifaddrs>) -> DataUsageInfo? {
        let pointer = infoPointer
        let name: String! = String(cString: pointer.pointee.ifa_name)
        let addr = pointer.pointee.ifa_addr.pointee
        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>?
        var dataUsageInfo = DataUsageInfo()

        if name.hasPrefix(wifiInterfacePrefix) {
            networkData = unsafeBitCast(pointer.pointee.ifa_data, to: UnsafeMutablePointer<if_data>.self)
            if let data = networkData {
                dataUsageInfo.wifiSent += data.pointee.ifi_obytes
                dataUsageInfo.wifiReceived += data.pointee.ifi_ibytes
            }

        } else if name.hasPrefix(wwanInterfacePrefix) {
            networkData = unsafeBitCast(pointer.pointee.ifa_data, to: UnsafeMutablePointer<if_data>.self)
            if let data = networkData {
                dataUsageInfo.wirelessWanDataSent += data.pointee.ifi_obytes
                dataUsageInfo.wirelessWanDataReceived += data.pointee.ifi_ibytes
            }
        }

        return dataUsageInfo
    }
}

@Adnan Aftab 2016-11-20 19:36:44

Swift version of the accepted answer. I also break the code into smaller units.

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
    }
}

@Jim109 2015-06-09 19:41:15

To add to the accepted answer, its important to realize that the amount of data displayed by the interface overflows and restarts at 0 after every 4 GB, especially if you are using this code to calculate the difference between two readings. This is because ifi_obytes and ifi_ibytes are uint_32 and their max value is 4294967295.

Also, I recommend using unsigned ints for the variables containing the data sent and received. Regular ints have half the max value of an unsigned integer, so when adding ifi_obytes, it may cause an overflow.

unsigned int sent = 0;
sent += networkStatisc->ifi_obytes;

@Wiz 2012-05-22 20:10:50

it's important to understand that these counters are provided since the device's last boot.

So, to make effective use of them, you should accompany every sample with the device's uptime (you can use mach_absolute_time() - see this for more information)

Once you have counters samples + uptime you can have better heuristics as to data use...

@Bob Whiteman 2015-10-26 20:26:06

mach_absolute_time is not uptime. It is roughly the amount of time the CPU has been active. mach_absolute_time mostly stops counting when the device sleeps.

Related Questions

Sponsored Content

39 Answered Questions

[SOLVED] Passing Data between View Controllers

31 Answered Questions

[SOLVED] iPhone UITextField - Change placeholder text color

  • 2009-08-27 10:36:19
  • adam
  • 306973 View
  • 513 Score
  • 31 Answer
  • Tags:   ios uitextfield

45 Answered Questions

[SOLVED] How can I develop for iPhone using a Windows development machine?

  • 2008-08-22 13:35:01
  • ryan
  • 1074952 View
  • 1098 Score
  • 45 Answer
  • Tags:   ios windows macos

30 Answered Questions

[SOLVED] Determine device (iPhone, iPod Touch) with iPhone SDK

18 Answered Questions

[SOLVED] How to programmatically send SMS on the iPhone?

32 Answered Questions

[SOLVED] Can I embed a custom font in an iPhone application?

  • 2008-12-11 20:21:11
  • Airsource Ltd
  • 232121 View
  • 746 Score
  • 32 Answer
  • Tags:   ios cocoa-touch fonts

30 Answered Questions

[SOLVED] How to develop or migrate apps for iPhone 5 screen resolution?

17 Answered Questions

[SOLVED] Starting iPhone app development in Linux?

  • 2008-11-10 02:25:49
  • javac
  • 266944 View
  • 493 Score
  • 17 Answer
  • Tags:   ios linux

0 Answered Questions

How to judge a Network environment is Only-IPV6 in iOS

1 Answered Questions

iPhone Data Usage Monitoring

  • 2010-12-07 19:35:31
  • DanyO
  • 3453 View
  • 9 Score
  • 1 Answer
  • Tags:   iphone

Sponsored Content