iOS获取当前设备的信息-网络相关

最近在搞网络相关的SDK,将自己在项目中能够开放出来的,记录下来,其中很多用到了C,相当于一个工具。后期还会选择开放一些ping网络的工具,找链路节点的工具,最近就在搞这个。

获取当前设备的IP地址

对于公网的IP当然,在我们本地设备上是不能够获取到的,至少我没有找到方法获取到出口IP地址,但是局域网的IP还是能够获取到的,这里ipv4和ipv6 都能够获取出来

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
+ (NSString *)deviceIPAdress
{
NSString *address = @"";
struct ifaddrs *interfaces = NULL;
struct ifaddrs *temp_addr = NULL;
int success = 0;

success = getifaddrs(&interfaces);

if (success == 0) { // 0 表示获取成功

temp_addr = interfaces;
while (temp_addr != NULL) {

if ([[NSString stringWithUTF8String:temp_addr->ifa_name] isEqualToString:@"en0"] || [[NSString stringWithUTF8String:temp_addr->ifa_name] isEqualToString:@"pdp_ip0"])
{
//如果是IPV4地址,直接转化
if (temp_addr->ifa_addr->sa_family == AF_INET){

// Get NSString from C String
address = [self formatIPV4Address:((struct sockaddr_in *)temp_addr->ifa_addr)->sin_addr];
}

//如果是IPV6地址
else if (temp_addr->ifa_addr->sa_family == AF_INET6){
address = [self formatIPV6Address:((struct sockaddr_in6 *)temp_addr->ifa_addr)->sin6_addr];
if (address && ![address isEqualToString:@""] && ![address.uppercaseString hasPrefix:@"FE80"]) break;
}
}

temp_addr = temp_addr->ifa_next;
}
}

freeifaddrs(interfaces);

//以FE80开始的地址是单播地址
if (address && ![address isEqualToString:@""] && ![address.uppercaseString hasPrefix:@"FE80"]) {
return address;
} else {
return @"127.0.0.1";
}
}

获取当前设备网关地址

网关地址,通俗点 就是路由器的地址,也是相对于局域网 这里需要区分一下ipv4和ipv6,两种获取网关地址的方法是不一样

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
//ipv4网关地址
+ (NSString *)getGatewayIPV4Address
{

NSString *address = nil;

/* net.route.0.inet.flags.gateway */
int mib[] = {CTL_NET, PF_ROUTE, 0, AF_INET, NET_RT_FLAGS, RTF_GATEWAY};

size_t l;
char *buf, *p;
struct rt_msghdr *rt;
struct sockaddr *sa;
struct sockaddr *sa_tab[RTAX_MAX];
int i;

if (sysctl(mib, sizeof(mib) / sizeof(int), 0, &l, 0, 0) < 0) {
address = @"192.168.0.1";
}

if (l > 0) {
buf = malloc(l);
if (sysctl(mib, sizeof(mib) / sizeof(int), buf, &l, 0, 0) < 0) {
address = @"192.168.0.1";
}

for (p = buf; p < buf + l; p += rt->rtm_msglen) {
rt = (struct rt_msghdr *)p;
sa = (struct sockaddr *)(rt + 1);
for (i = 0; i < RTAX_MAX; i++) {
if (rt->rtm_addrs & (1 << i)) {
sa_tab[i] = sa;
sa = (struct sockaddr *)((char *)sa + ROUNDUP(sa->sa_len));
} else {
sa_tab[i] = NULL;
}
}

if (((rt->rtm_addrs & (RTA_DST | RTA_GATEWAY)) == (RTA_DST | RTA_GATEWAY)) &&
sa_tab[RTAX_DST]->sa_family == AF_INET &&
sa_tab[RTAX_GATEWAY]->sa_family == AF_INET) {
unsigned char octet[4] = {0, 0, 0, 0};
int i;
for (i = 0; i < 4; i++) {
octet[i] = (((struct sockaddr_in *)(sa_tab[RTAX_GATEWAY]))->sin_addr.s_addr >>
(i * 8)) &
0xFF;
}
if (((struct sockaddr_in *)sa_tab[RTAX_DST])->sin_addr.s_addr == 0) {
in_addr_t addr =
((struct sockaddr_in *)(sa_tab[RTAX_GATEWAY]))->sin_addr.s_addr;
address = [self formatIPV4Address:*((struct in_addr *)&addr)];
// NSLog(@"IPV4address%@", address);
break;
}
}
}
free(buf);
}

return address;
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
//ipv6网关地址
+ (NSString *)getGatewayIPV6Address
{

NSString *address = nil;

/* net.route.0.inet.flags.gateway */
int mib[] = {CTL_NET, PF_ROUTE, 0, AF_INET6, NET_RT_FLAGS, RTF_GATEWAY};

size_t l;
char *buf, *p;
struct rt_msghdr *rt;
struct sockaddr_in6 *sa;
struct sockaddr_in6 *sa_tab[RTAX_MAX];
int i;

if (sysctl(mib, sizeof(mib) / sizeof(int), 0, &l, 0, 0) < 0) {
address = @"192.168.0.1";
}

if (l > 0) {
buf = malloc(l);
if (sysctl(mib, sizeof(mib) / sizeof(int), buf, &l, 0, 0) < 0) {
address = @"192.168.0.1";
}

for (p = buf; p < buf + l; p += rt->rtm_msglen) {
rt = (struct rt_msghdr *)p;
sa = (struct sockaddr_in6 *)(rt + 1);
for (i = 0; i < RTAX_MAX; i++) {
if (rt->rtm_addrs & (1 << i)) {
sa_tab[i] = sa;
sa = (struct sockaddr_in6 *)((char *)sa + sa->sin6_len);
} else {
sa_tab[i] = NULL;
}
}

if( ((rt->rtm_addrs & (RTA_DST|RTA_GATEWAY)) == (RTA_DST|RTA_GATEWAY))
&& sa_tab[RTAX_DST]->sin6_family == AF_INET6
&& sa_tab[RTAX_GATEWAY]->sin6_family == AF_INET6)
{
address = [self formatIPV6Address:((struct sockaddr_in6 *)(sa_tab[RTAX_GATEWAY]))->sin6_addr];
// NSLog(@"IPV6address%@", address);
break;
}
}
free(buf);
}

return address;
}

我们在获取的时候判断一下

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
/*!
* 获取当前设备网关地址
*/
+ (NSString *)getGatewayIPAddress{
NSString *address = nil;

NSString *gatewayIPV4 = [self getGatewayIPV4Address];
NSString *gatewayIPV6 = [self getGatewayIPV6Address];

if (gatewayIPV6 != nil) {
address = gatewayIPV6;
} else {
address = gatewayIPV4;
}

return address;
}

通过域名拿到域名对应的IP地址(CDN)

通过域名拿到的IP地址,一般来说,如果买了CDN的话,拿到的Ip都会是多个IP

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59

/*!
* 通过hostname获取ip列表 DNS解析地址
*/
+ (NSArray *)getDNSsWithDormain:(NSString *)hostName{
NSMutableArray *result = [[NSMutableArray alloc] init];
NSArray *IPDNSs = [self getDNSWithHostName:hostName];
if (IPDNSs && IPDNSs.count > 0) {
[result addObjectsFromArray:IPDNSs];
}

return [NSArray arrayWithArray:result];
}


+ (NSArray *)getDNSWithHostName:(NSString *)hostName
{
const char *hostN = [hostName UTF8String];
Boolean result = false;
Boolean bResolved = false;
CFHostRef hostRef;
CFArrayRef addresses = NULL;

CFStringRef hostNameRef = CFStringCreateWithCString(kCFAllocatorDefault, hostN, kCFStringEncodingASCII);

hostRef = CFHostCreateWithName(kCFAllocatorDefault, hostNameRef);
if (hostRef) {
result = CFHostStartInfoResolution(hostRef, kCFHostAddresses, NULL);
if (result == true) {
addresses = CFHostGetAddressing(hostRef, &result);
}
}
bResolved = result;
NSMutableArray *ipAddresses = [NSMutableArray array];
if(bResolved)
{
struct sockaddr_in* remoteAddr;

for(int i = 0; i < CFArrayGetCount(addresses); i++)
{
CFDataRef saData = (CFDataRef)CFArrayGetValueAtIndex(addresses, i);
remoteAddr = (struct sockaddr_in*)CFDataGetBytePtr(saData);

if(remoteAddr != NULL)
{
//获取IP地址
const char *strIP41 = inet_ntoa(remoteAddr->sin_addr);
NSString *strDNS =[NSString stringWithCString:strIP41 encoding:NSASCIIStringEncoding];
[ipAddresses addObject:strDNS];
}
}
}
CFRelease(hostNameRef);
if (hostRef) {
CFRelease(hostRef);
}

return [NSArray arrayWithArray:ipAddresses];
}

获取当前的网络状况

如果是WIFI环境,直接返回wifi 如果是蜂窝网络环境,那么还可以区分到底是那个运营商,还可以区分是使用的什么网络,4G 3G 2G等 运营商暂时区分了国内的三大运营商,如果还需要区分国外的,可以维基百科上查对应的code

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54

+(NSString *)currentNetInfo{

NSString *returnName = nil;

PPSNetWorkType type = [PPSGetAppEnvironment getNetworkTypeFromStatusBar];
if (type == PPSNetWorkTypeWiFi) {
returnName = @"WIFI";
return returnName;
}

NSString *carrierName = nil;
CTTelephonyNetworkInfo *netInfo = [[CTTelephonyNetworkInfo alloc] init];
CTCarrier *carrier = [netInfo subscriberCellularProvider];
if (carrier != NULL) {
NSArray *chinaMobileMics = @[@"0",@"2",@"7"];//移动code
NSArray *chinaTelecomMics = @[@"3",@"5",@"11"];//电信code
NSArray *chinaUnicomMics = @[@"1",@"6"];//联通code
NSString *mobileNetworkCode = [carrier mobileNetworkCode];
if ([chinaMobileMics containsObject:mobileNetworkCode]) {
carrierName = @"chinamobile";
}else if ([chinaTelecomMics containsObject:mobileNetworkCode]){
carrierName = @"chinatelecom";
}else if ([chinaUnicomMics containsObject:mobileNetworkCode]){
carrierName = @"chinaunicom";
}else{
carrierName = @"unknown";
}
} else {
carrierName = @"unknown";
}

switch (type) {
case PPSNetWorkType2G:
returnName = [NSString stringWithFormat:@"%@_%@",carrierName,@"2G"];
break;
case PPSNetWorkType3G:
returnName = [NSString stringWithFormat:@"%@_%@",carrierName,@"3G"];
break;
case PPSNetWorkType4G:
returnName = [NSString stringWithFormat:@"%@_%@",carrierName,@"4G"];
break;
case PPSNetWorkType5G:
returnName = [NSString stringWithFormat:@"%@_%@",carrierName,@"5G"];
break;
case PPSNetWorkTypeNone:
returnName = [NSString stringWithFormat:@"%@_%@",carrierName,@"unknown"];
break;
default:
returnName = [NSString stringWithFormat:@"%@_%@",carrierName,@"unknown"];
break;
}
return returnName;
}

获取当前的设备信息

获取当前设备的信息,是iPhone 4 5 6 7还是 等等 还有系统的版本号 手机、平板
之类的都能够去区分出来

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88

/**
获取设备的类型

@return 设备类型
*/
+ (NSString *)deviceInfo {
struct utsname systemInfo;

uname(&systemInfo);

NSString* code = [NSString stringWithCString:systemInfo.machine
encoding:NSUTF8StringEncoding];

static NSDictionary* deviceNamesByCode = nil;

if (!deviceNamesByCode) {

deviceNamesByCode = @{@"i386" :@"Simulator",
@"x86_64" :@"Simulator",
@"iPod1,1" :@"iPod Touch", // (Original)
@"iPod2,1" :@"iPod Touch", // (Second Generation)
@"iPod3,1" :@"iPod Touch", // (Third Generation)
@"iPod4,1" :@"iPod Touch", // (Fourth Generation)
@"iPod7,1" :@"iPod Touch", // (6th Generation)
@"iPhone1,1" :@"iPhone", // (Original)
@"iPhone1,2" :@"iPhone", // (3G)
@"iPhone2,1" :@"iPhone", // (3GS)
@"iPad1,1" :@"iPad", // (Original)
@"iPad2,1" :@"iPad 2", //
@"iPad3,1" :@"iPad", // (3rd Generation)
@"iPhone3,1" :@"iPhone 4", // (GSM)
@"iPhone3,3" :@"iPhone 4", // (CDMA/Verizon/Sprint)
@"iPhone4,1" :@"iPhone 4S", //
@"iPhone5,1" :@"iPhone 5", // (model A1428, AT&T/Canada)
@"iPhone5,2" :@"iPhone 5", // (model A1429, everything else)
@"iPad3,4" :@"iPad", // (4th Generation)
@"iPad2,5" :@"iPad Mini", // (Original)
@"iPhone5,3" :@"iPhone 5c", // (model A1456, A1532 | GSM)
@"iPhone5,4" :@"iPhone 5c", // (model A1507, A1516, A1526 (China), A1529 | Global)
@"iPhone6,1" :@"iPhone 5s", // (model A1433, A1533 | GSM)
@"iPhone6,2" :@"iPhone 5s", // (model A1457, A1518, A1528 (China), A1530 | Global)
@"iPhone7,1" :@"iPhone 6 Plus", //
@"iPhone7,2" :@"iPhone 6", //
@"iPhone8,1" :@"iPhone 6S", //
@"iPhone8,2" :@"iPhone 6S Plus", //
@"iPhone8,4" :@"iPhone SE", //
@"iPhone9,1" :@"iPhone 7", //
@"iPhone9,3" :@"iPhone 7", //
@"iPhone9,2" :@"iPhone 7 Plus", //
@"iPhone9,4" :@"iPhone 7 Plus", //

@"iPad4,1" :@"iPad Air", // 5th Generation iPad (iPad Air) - Wifi
@"iPad4,2" :@"iPad Air", // 5th Generation iPad (iPad Air) - Cellular
@"iPad4,4" :@"iPad Mini", // (2nd Generation iPad Mini - Wifi)
@"iPad4,5" :@"iPad Mini", // (2nd Generation iPad Mini - Cellular)
@"iPad4,7" :@"iPad Mini", // (3rd Generation iPad Mini - Wifi (model A1599))
@"iPad6,7" :@"iPad Pro (12.9\")", // iPad Pro 12.9 inches - (model A1584)
@"iPad6,8" :@"iPad Pro (12.9\")", // iPad Pro 12.9 inches - (model A1652)
@"iPad6,3" :@"iPad Pro (9.7\")", // iPad Pro 9.7 inches - (model A1673)
@"iPad6,4" :@"iPad Pro (9.7\")" // iPad Pro 9.7 inches - (models A1674 and A1675)
};
}

NSString* deviceName = [deviceNamesByCode objectForKey:code];

if (!deviceName) {
// Not found on database. At least guess main device type from string contents:

if ([code rangeOfString:@"iPod"].location != NSNotFound) {
deviceName = @"iPod Touch";
}
else if([code rangeOfString:@"iPad"].location != NSNotFound) {
deviceName = @"iPad";
}
else if([code rangeOfString:@"iPhone"].location != NSNotFound){
deviceName = @"iPhone";
}
else {
deviceName = @"Unknown";
}
}

UIDevice *device = [UIDevice currentDevice];
NSString *systemVersion = [device systemVersion];

return [NSString stringWithFormat:@"iOS#%@#%@",deviceName,systemVersion];
}

获取的信息:

原项目地址:

https://github.com/yangqian111/blog/tree/master/iOS获取当前设备的信息-网络相关