我已经搜索了这个主题,但发现很少有帮助的细节。有了这些细节,我试着编写一些代码,如下所示。
注意:在将本文标记为重复之前,请将此帖子中共享的详细信息与其他帖子进行比较,而不仅仅是按主题进行比较。
- (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_opackets
和ifi_ipackets
格式的WiFi使用情况。
我还想补充说,如果我连接到WiFi网络,但没有使用互联网,我仍然可以获得ifi_obytes
和ifi_ibytes
的附加值。
也许我在实现或理解上是错误的。需要有人来帮我。
编辑:我尝试了AF_INET
而不是AF_LINK
(sockaddr_in
而不是sockaddr_dl
)。这会使应用程序崩溃。
发布于 2011-11-05 02:21:34
问题是pdp_ip0
是其中的一个接口,所有的pdpXXX
都是专用于不同功能的WWAN
接口,语音信箱,通用网络接口。
我在Apple论坛上读到:操作系统不会以进程为单位保存网络统计数据。因此,这个问题没有确切的解决方案。但是,您可以获取每个网络接口的网络统计信息。
通常,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)};
}
改进了对复制/粘贴的支持!
发布于 2012-05-23 04:10:51
重要的是要理解,这些计数器是自设备上次启动以来提供的。
因此,为了有效地利用它们,您应该将每个样本与设备的正常运行时间一起使用(您可以使用mach_absolute_time()
-有关更多信息,请参阅this )
一旦你有了计数器样本+正常运行时间,你就可以有更好的启发式数据使用……
发布于 2015-06-10 03:41:15
要添加到可接受的答案中,重要的是要认识到接口显示的数据量在每次4 GB
后溢出并在0
重新启动,特别是当您使用此代码计算两个读数之间的差值时。这是因为ifi_obytes
和ifi_ibytes
是uint_32
,它们的最大值是4294967295
。
另外,我建议对包含发送和接收的数据的变量使用unsigned int
。常规int
的最大值是无符号整数的一半,因此在添加ifi_obytes
时,可能会导致溢出。
unsigned int sent = 0;
sent += networkStatisc->ifi_obytes;
https://stackoverflow.com/questions/7946699
复制相似问题