iPhone数据使用情况跟踪/监测

我已经search了这个主题,但发现很less的细节是有帮助的。 有了这些细节,我试图做一些代码如下。

注意:请将此post中的详细信息与其他post进行比较,然后将其标记为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]; } 

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

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

也想补充说,如果我连接到一个WiFinetworking,但不使用互联网,我仍然获得价值增加到ifi_obytesifi_ibytes

可能是我在实施或理解上是错误的。 需要有人来帮助我。


编辑:而不是AF_LINK我试着AF_INETsockaddr_in而不是sockaddr_dl )。 这使应用程序崩溃。

问题是,pdp_ip0是接口之一,所有的pdpXXX都是专用于不同function的WWAN接口,语音邮件,一般networking接口。

我在苹果论坛上读到:操作系统不会逐个进程地保留networking统计信息。 因此,这个问题没有确切的解决办法。 但是,您可以获取每个networking接口的networking统计信息。

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

没有好的方式来获取信息的WiFi /蜂窝networking数据,因为,特定的date时间!

数据统计信息(ifa_data-> ifi_obytes和ifa_data-> ifi_ibytes)是从以前的设备重新启动存储的。

我不知道为什么,但是ifi_opackets和ifi_ipackets只显示lo0(我认为它的主界面)。

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

 #include <arpa/inet.h> #include <net/if.h> #include <ifaddrs.h> #include <net/if_dl.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 = [NSString stringWithFormat:@"%s",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:[NSNumber numberWithUnsignedInt:WiFiSent], DataCounterKeyWiFiReceived:[NSNumber numberWithUnsignedInt:WiFiReceived], DataCounterKeyWWANSent:[NSNumber numberWithUnsignedInt:WWANSent], DataCounterKeyWWANReceived:[NSNumber numberWithUnsignedInt:WWANReceived]}; } 

改进的复制/粘贴支持!

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

因此,要有效地使用它们,您应该随设备的正常运行时间陪同每个样本(可以使用mach_absolute_time() – 请参阅此部分以获取更多信息)

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

要增加接受的答案,重要的是要意识到接口显示的数据量会在每4GB后在0处溢出并重新启动,特别是如果使用此代码计算两个读数之间的差异。 这是因为ifi_obytes和ifi_ibytes是uint_32,它们的最大值是4294967295。

另外,我build议使用无符号整数来包含发送和接收数据的variables。 常规整数的无符号整数的最大值的一半,所以当添加ifi_obytes时,可能会导致溢出。

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

Swift版本的接受答案。 我也把代码分解成更小的单元。

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

我将以上源代码固定到Swift3版本

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