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