아이폰 데이터 사용량 추적/모니터링
저는 이 주제를 검색해 보았지만 도움이 되는 세부 사항을 거의 찾지 못했습니다.이 세부 사항들을 가지고 저는 다음과 같은 코드를 요리해 보았습니다.
참고: 이 게시물에 공유된 내용을 주제별뿐만 아니라 중복으로 표시하기 전에 다른 게시물과 비교하십시오.
- (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];
}
이 코드는 아이폰 장치의 인터넷 사용 정보를 수집합니다(내 응용 프로그램만 수집하지 않음).
이제 WiFi 또는 3G를 통해 인터넷을 사용하면 데이터(바이트)만 수신됩니다.ifi_obytes
(발송) 및ifi_ibytes
(수신) 하지만 와이파이를 사용해야 할 것 같습니다.ifi_opackets
그리고.ifi_ipackets
.
또한 WiFi 네트워크에 연결되어 있지만 인터넷을 사용하지 않는 경우에도 다음과 같은 추가 가치를 얻을 수 있습니다.ifi_obytes
그리고.ifi_ibytes
.
구현이나 이해가 잘못되었을 수 있습니다.날 도와줄 사람이 필요해요.
편집: 대신AF_LINK
나는 노력했다.AF_INET
(sockaddr_in
대신에sockaddr_dl
응용 프로그램이 충돌합니다.
중요한 것은pdp_ip0
인터페이스 중 하나임, 모두pdpXXX
이다WWAN
다양한 기능, 음성 메일, 일반 네트워킹 인터페이스 전용 인터페이스.
나는 애플 포럼에서 읽었다: OS는 프로세스별로 네트워크 통계를 유지하지 않습니다.따라서 이 문제에 대한 정확한 해결책은 없습니다.그러나 각 네트워크 인터페이스에 대한 네트워크 통계를 가져올 수 있습니다.
일반적으로en0
당신의Wi-Fi
인터페이스 및pdp_ip0
당신의WWAN
인터페이스
특정 날짜 시간 이후에는 정보 와이파이/휴대전화 네트워크 데이터를 얻을 수 있는 좋은 방법이 없습니다!
데이터 통계량(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는 보내고 받은 데이터를 포함하는 변수입니다.으로.int
는 부호 이므로 s를 는 부 호 없 정 의 최 의 때 로 므 있 추 할 가 으 고 가ifi_obytes
오버플로를 일으킬 수 있습니다.
unsigned int sent = 0;
sent += networkStatisc->ifi_obytes;
승인된 답변의 빠른 버전입니다.코드를 더 작은 단위로 나누기도 합니다.
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
}
}
이전 버전을 기반으로 하지만 Swift4 및 Xcode9에 맞게 수정된 새로운 버전
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
}
}
다시 한번 같은 답변을 드려서 죄송합니다.
하지만 UInt32가 충분하지 않아서 너무 커지면 충돌합니다.
방금 UInt32를 UInt64로 변경했는데 작동이 잘 됩니다.
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' 카테고리의 다른 글
이전 인쇄물을 stdout으로 덮어쓰는 방법은 무엇입니까? (0) | 2023.06.14 |
---|---|
C에서 EOF와 '\0'의 값은 무엇입니까? (0) | 2023.06.14 |
사용자가 Firebase에서 로그아웃하도록 하는 방법은 무엇입니까? (0) | 2023.06.14 |
아이폰 6 및 6 Plus에서 앱의 기본 해상도를 활성화하는 방법은 무엇입니까? (0) | 2023.06.14 |
Woocommerce Plugin에서 등급의_comment_meta()를 가져오려면 어떻게 해야 합니까? (0) | 2023.06.14 |