iOS 获取IP类型和地址
2019-07-05 本文已影响0人
罗显友
一贯面向百度编程的我,在面对这个获取IP类型和地址的需求时,发现百度真的是很无力。于是整合了几篇别人写的文章,实现了我这个需求。
我的需求就是,我可能只获取当前的网络IP类型,也可能只获取IP地址,也可能都获取。但是网上的一些方法都是需要我自己传入一个是否是IPV4的参数才能获取到IP地址,所以不能满足我的需求。
这个类提供了两个方法
1.获取IP地址
2.获取IP类型(IPV4和IPV6)
IP地址和IP类型是对应的,比如,IP地址是:192.168.123 这个类型就是IPV4
IP地址是:200:12133::124w:dsdd 这个类型就是IPV6
.h文件代码
// Created by 罗小友 on 2019/6/24.
// Copyright © 2019 DCloud. All rights reserved.
//
#import <Foundation/Foundation.h>
NS_ASSUME_NONNULL_BEGIN
@interface ZJPhoneIPAddress : NSObject
- (NSString *)getIPType; //获取IP类型
- (NSString *)getIPAddress; //获取IP地址
@end
NS_ASSUME_NONNULL_END
.m文件代码
// Created by 罗小友 on 2019/6/24.
// Copyright © 2019 DCloud. All rights reserved.
#import "ZJPhoneIPAddress.h" //我自己的获取IP地址和类型的类
//需要导入的头文件
#include <ifaddrs.h>
#include <arpa/inet.h>
#include <net/if.h>
//我自己的测试数据
/*
如果只有移动网路或者无网络,取出来的信息如下
{
"en2/ipv4" = "169.254.92.206";
"en2/ipv6" = "fe80::d1:3900:74f4:1b02";
"lo0/ipv4" = "127.0.0.1";
"lo0/ipv6" = "fe80::1";
"utun0/ipv6" = "fe80::af12:4c52:e7ac:2113";
}
判断结论:移动网络下只会 en2对应的IPV4地址是对的 ,所以对en2进行Ipv4正则判断,然后返回出去
如果只有wifi或者与移动网络共存(默认是优先使用wifi),则取出来的信息如下
{
"awdl0/ipv6" = "fe80::5814:42ff:fe7f:95f";
"en0/ipv4" = "192.168.1.130";
"en0/ipv6" = "fe80::1c83:2885:513b:29a5";
"en2/ipv4" = "169.254.92.206";
"en2/ipv6" = "fe80::d1:3900:74f4:1b02";
"lo0/ipv4" = "127.0.0.1";
"lo0/ipv6" = "fe80::1";
"utun0/ipv6" = "fe80::af12:4c52:e7ac:2113";
}
判断为:此时只需要先取出wifi网络下的en0,然后判断IPV4是否合法,然后返回取出
如果连接的是ipv6网络,则取出的数据如下:
{
"awdl0/ipv6" = "fe80::5814:42ff:fe7f:95f";
"en0/ipv4" = "169.254.2.169";
"en0/ipv6" = "2001:2::aab1:b97d:f42b:c235:46b8";
"en2/ipv4" = "169.254.92.206";
"en2/ipv6" = "fe80::d1:3900:74f4:1b02";
"lo0/ipv4" = "127.0.0.1";
"lo0/ipv6" = "fe80::1";
"utun0/ipv6" = "fe80::af12:4c52:e7ac:2113";
}
此时只需要先取出wifi网络下的en0/ipv6, 然后用取出的值来判断是否是IPv6,然后返回对应的值
*/
#define IOS_CELLULAR @"pdp_ip0" //未知
#define IOS_WIFI @"en0" //wifi
#define IOS_4_3G @"en2" //移动网络
#define IOS_VPN @"utun0" //vpn
#define IP_ADDR_IPv4 @"ipv4"
#define IP_ADDR_IPv6 @"ipv6"
@implementation ZJPhoneIPAddress
//获取IP地址
- (NSString *)getIPAddress
{
//依照这些key,去取出相对应的IP地址
NSArray *searchArray =
@[ IOS_VPN @"/" IP_ADDR_IPv4, IOS_VPN @"/" IP_ADDR_IPv6, IOS_WIFI @"/" IP_ADDR_IPv4, IOS_WIFI @"/" IP_ADDR_IPv6, IOS_4_3G @"/" IP_ADDR_IPv4, IOS_4_3G @"/" IP_ADDR_IPv6, IOS_CELLULAR @"/" IP_ADDR_IPv4, IOS_CELLULAR @"/" IP_ADDR_IPv6];
__block NSDictionary *addresses = [self getIPAddressArray];
NSLog(@"获取到的整个IP信息addresses: %@", addresses);
__block NSString *address;
[searchArray enumerateObjectsUsingBlock:^(NSString *key, NSUInteger idx, BOOL *stop)
{
address = addresses[key];
if ([key rangeOfString:@"ipv6"].length > 0 && ![[NSString stringWithFormat:@"%@",addresses[key]] hasPrefix:@"(null)"] ) {
if ( ![addresses[key] hasPrefix:@"fe80"]) {
// isIpv6 = YES;
NSLog(@"是ivp6,退出循环,打印当前IP:%@",address);
*stop = YES;
}
}else{
if([self isValidatIP:address]) {
NSLog(@"是ivp4,退出循环,打印当前IP:%@",address);
*stop = YES;
}
}
} ];
return address ? address : @"";
}
//获取IP地址的类型
- (NSString *)getIPType{
NSString *ipAddress = [self getIPAddress];
if ([self isValidatIP:ipAddress]) {
return @"04";//ipv4
}else{
return @"06";//ipv6
}
}
//获取IP相关信息
-(NSDictionary *)getIPAddressArray
{
NSMutableDictionary *addresses = [NSMutableDictionary dictionaryWithCapacity:8];
// retrieve the current interfaces - returns 0 on success
struct ifaddrs *interfaces;
if(!getifaddrs(&interfaces)) {
// Loop through linked list of interfaces
struct ifaddrs *interface;
for(interface=interfaces; interface; interface=interface->ifa_next) {
if(!(interface->ifa_flags & IFF_UP) /* || (interface->ifa_flags & IFF_LOOPBACK) */ ) {
continue; // deeply nested code harder to read
}
const struct sockaddr_in *addr = (const struct sockaddr_in*)interface->ifa_addr;
char addrBuf[ MAX(INET_ADDRSTRLEN, INET6_ADDRSTRLEN) ];
if(addr && (addr->sin_family==AF_INET || addr->sin_family==AF_INET6)) {
NSString *name = [NSString stringWithUTF8String:interface->ifa_name];
NSString *type;
if(addr->sin_family == AF_INET) {
if(inet_ntop(AF_INET, &addr->sin_addr, addrBuf, INET_ADDRSTRLEN)) {
type = IP_ADDR_IPv4;
}
} else {
const struct sockaddr_in6 *addr6 = (const struct sockaddr_in6*)interface->ifa_addr;
if(inet_ntop(AF_INET6, &addr6->sin6_addr, addrBuf, INET6_ADDRSTRLEN)) {
type = IP_ADDR_IPv6;
}
}
if(type) {
NSString *key = [NSString stringWithFormat:@"%@/%@", name, type];
addresses[key] = [NSString stringWithUTF8String:addrBuf];
}
}
}
// Free memory
freeifaddrs(interfaces);
}
return [addresses count] ? addresses : nil;
}
//判断当前网络IP是否是Ipv4,如果是YES 否则NO
- (BOOL)isValidatIP:(NSString *)ipAddress {
if (ipAddress.length == 0) {
return NO;
}
NSString *urlRegEx = @"^([01]?\\d\\d?|2[0-4]\\d|25[0-5])\\."
"([01]?\\d\\d?|2[0-4]\\d|25[0-5])\\."
"([01]?\\d\\d?|2[0-4]\\d|25[0-5])\\."
"([01]?\\d\\d?|2[0-4]\\d|25[0-5])$";
NSError *error;
NSRegularExpression *regex = [NSRegularExpression regularExpressionWithPattern:urlRegEx options:0 error:&error];
if (regex != nil) {
NSTextCheckingResult *firstMatch=[regex firstMatchInString:ipAddress options:0 range:NSMakeRange(0, [ipAddress length])];
if (firstMatch) {
NSRange resultRange = [firstMatch rangeAtIndex:0];
NSString *result=[ipAddress substringWithRange:resultRange];
//输出结果
NSLog(@"%@",result);
return YES;
}
}
return NO;
}
@end