iPhone 데이터 사용량 추적 / 모니터링
나는이 주제를 검색했지만 도움이되는 세부 사항을 거의 발견하지 못했습니다. 이러한 세부 사항으로 다음과 같이 코드를 요리하려고했습니다.
참고 :이 게시물에서 공유 된 세부 사항을 주제가 아닌 복제본으로 표시하기 전에 다른 게시물과 비교하십시오.
- (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
(수신) 에서만 데이터 (바이트) 를 얻지 만 WiFi 사용을 ifi_opackets
및로 가져와야한다고 생각합니다 ifi_ipackets
.
또한 내가 WiFi 네트워크에 연결 해요,하지만 인터넷을 사용하고 있지 않다 경우, 난 여전히 가치가 추가됩니다 것을 추가하고 싶어 ifi_obytes
하고 ifi_ibytes
.
구현 또는 이해가 잘못되었을 수 있습니다. 나를 도울 사람이 필요합니다.
편집 : 대신 () 대신 AF_LINK
시도했습니다 . 응용 프로그램이 충돌합니다.AF_INET
sockaddr_in
sockaddr_dl
문제는 즉 pdp_ip0
모두가 인터페이스 중 하나 pdpXXX
입니다 WWAN
다른 기능, 음성 메일, 일반 네트워킹 인터페이스 전용 인터페이스.
Apple 포럼에서 읽은 내용은 다음과 같습니다. OS는 프로세스별로 네트워크 통계를 유지하지 않습니다. 따라서이 문제에 대한 정확한 해결책은 없습니다. 그러나 각 네트워크 인터페이스에 대한 네트워크 통계를 얻을 수 있습니다.
일반적으로 en0
당신이다 Wi-Fi
인터페이스와 pdp_ip0
사용자입니다 WWAN
인터페이스를 제공합니다.
특정 날짜-시간 이후로 정보 wifi / 셀룰러 네트워크 데이터를 얻는 좋은 방법은 없습니다!
데이터 통계 ( ifa_data->ifi_obytes
및 ifa_data->ifi_ibytes
)는 이전 장치 재부팅에서 저장됩니다.
왜 그런지 모르겠지만, ifi_opackets
및 ifi_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)};
}
향상된 복사 / 붙여 넣기 지원!
이 카운터는 장치의 마지막 부팅 이후 에 제공된다는 것을 이해해야합니다 .
따라서 효과적으로 사용하려면 모든 샘플을 장치의 가동 시간과 함께 제공해야합니다 (사용할 수 있습니다 mach_absolute_time()
- 자세한 내용 은 이것을 참조하십시오)
카운터 샘플 + 가동 시간을 확보하면 데이터 사용에 대해 더 나은 휴리스틱을 얻을 수 있습니다.
허용 된 답변에 추가하려면 인터페이스가 표시하는 데이터의 양이 0
매번 후에 오버플로되고 다시 시작된다는 것을 인식하는 것이 중요합니다 4 GB
. 특히이 코드를 사용하여 두 판독 값의 차이를 계산하는 경우 특히 그렇습니다. 때문입니다 ifi_obytes
하고 ifi_ibytes
있는 uint_32
자신의 최대 값입니다 4294967295
.
또한 unsigned int
보내고받은 데이터가 포함 된 변수에 s를 사용하는 것이 좋습니다 . regular int
에는 부호없는 정수의 최대 값의 절반이 있으므로을 추가 ifi_obytes
하면 오버플로가 발생할 수 있습니다.
unsigned int sent = 0;
sent += networkStatisc->ifi_obytes;
위의 소스 코드를 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
}
}
허용되는 답변의 신속한 버전. 또한 코드를 더 작은 단위로 나눕니다.
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
}
}
이전 버전을 기반으로하지만 Swift4 및 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
}
}
같은 답변으로 다시 죄송합니다.
but I found that UInt32 is not enough, so it crashes when it became too big.
I just changed UInt32 to UInt64 and it works fine.
struct DataUsageInfo {
var wifiReceived: UInt64 = 0
var wifiSent: UInt64 = 0
var wirelessWanDataReceived: UInt64 = 0
var wirelessWanDataSent: UInt64 = 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 += UInt64(networkData?.pointee.ifi_obytes ?? 0)
dataUsageInfo.wifiReceived += UInt64(networkData?.pointee.ifi_ibytes ?? 0)
} else if name.hasPrefix(wwanInterfacePrefix) {
networkData = unsafeBitCast(pointer.pointee.ifa_data, to: UnsafeMutablePointer<if_data>.self)
dataUsageInfo.wirelessWanDataSent += UInt64(networkData?.pointee.ifi_obytes ?? 0)
dataUsageInfo.wirelessWanDataReceived += UInt64(networkData?.pointee.ifi_ibytes ?? 0)
}
return dataUsageInfo
}
}
참고URL : https://stackoverflow.com/questions/7946699/iphone-data-usage-tracking-monitoring
'programing tip' 카테고리의 다른 글
Java 정적 이니셜 라이저 스레드는 안전합니까? (0) | 2020.06.25 |
---|---|
Java에서 메모리를 비우는 방법? (0) | 2020.06.25 |
SPAN 대 DIV (인라인 블록) (0) | 2020.06.25 |
힘내 : 병합 커밋의 메시지를 편집 / 변경하는 방법은 무엇입니까? (0) | 2020.06.25 |
jQuery document.ready 대 자체 호출 익명 함수 (0) | 2020.06.25 |