Tôi muốn lấy địa chỉ IP của iPad theo chương trình. Làm cách nào tôi có thể truy vấn hệ thống con mạng để tìm hiểu địa chỉ IPv4 (và IPv6) của tôi là gì?
PS: Tôi có thể tắt IPv6 bằng cách nào đó không?
Tôi muốn lấy địa chỉ IP của iPad theo chương trình. Làm cách nào tôi có thể truy vấn hệ thống con mạng để tìm hiểu địa chỉ IPv4 (và IPv6) của tôi là gì?
PS: Tôi có thể tắt IPv6 bằng cách nào đó không?
Câu trả lời:
Đoạn mã sau tìm thấy tất cả địa chỉ IPv4 và IPv6 trên thiết bị iOS hoặc OSX. getIPAddress
Phương thức đầu tiên hoạt động ít nhiều như mã cũ hơn trong câu trả lời này: bạn có thể thích một hoặc một địa chỉ loại khác và nó luôn thích WIFI hơn di động (rõ ràng bạn có thể thay đổi điều này).
Thú vị hơn, nó có thể trả về một từ điển của tất cả các địa chỉ được tìm thấy, bỏ qua địa chỉ cho các not up
giao diện hoặc địa chỉ được liên kết loopback
. Mã trước đó cũng như các giải pháp khác về chủ đề này sẽ không giải mã đúng IPv6 (inet_ntoa không thể xử lý chúng). Điều này đã được Jens Alfke chỉ ra cho tôi trên một diễn đàn của Apple - chức năng phù hợp để sử dụng là inet_ntop (xem trang người đàn ông và tham khảo bài viết inet_ntop này cũng do Jens cung cấp.
Các khóa từ điển có dạng "giao diện" "/" "ipv4 hoặc ipv6".
#include <ifaddrs.h>
#include <arpa/inet.h>
#include <net/if.h>
#define IOS_CELLULAR @"pdp_ip0"
#define IOS_WIFI @"en0"
//#define IOS_VPN @"utun0"
#define IP_ADDR_IPv4 @"ipv4"
#define IP_ADDR_IPv6 @"ipv6"
- (NSString *)getIPAddress:(BOOL)preferIPv4
{
NSArray *searchArray = preferIPv4 ?
@[ /*IOS_VPN @"/" IP_ADDR_IPv4, IOS_VPN @"/" IP_ADDR_IPv6,*/ IOS_WIFI @"/" IP_ADDR_IPv4, IOS_WIFI @"/" IP_ADDR_IPv6, IOS_CELLULAR @"/" IP_ADDR_IPv4, IOS_CELLULAR @"/" IP_ADDR_IPv6 ] :
@[ /*IOS_VPN @"/" IP_ADDR_IPv6, IOS_VPN @"/" IP_ADDR_IPv4,*/ IOS_WIFI @"/" IP_ADDR_IPv6, IOS_WIFI @"/" IP_ADDR_IPv4, IOS_CELLULAR @"/" IP_ADDR_IPv6, IOS_CELLULAR @"/" IP_ADDR_IPv4 ] ;
NSDictionary *addresses = [self getIPAddresses];
NSLog(@"addresses: %@", addresses);
__block NSString *address;
[searchArray enumerateObjectsUsingBlock:^(NSString *key, NSUInteger idx, BOOL *stop)
{
address = addresses[key];
if(address) *stop = YES;
} ];
return address ? address : @"0.0.0.0";
}
- (NSDictionary *)getIPAddresses
{
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;
}
EDIT1: Mã được cập nhật vào ngày 16 tháng 5 năm 2014 (lỗi được chỉ ra bởi lhunath, xem bình luận). Địa chỉ Loopback hiện đã được trả lại, nhưng bạn có thể dễ dàng bỏ qua bài kiểm tra để tự loại trừ chúng.
EDIT2: (bởi một số người chưa biết): Đã cải thiện hơn nữa vào ngày 13 tháng 3 năm 2015: Trong trường hợp người dùng sử dụng VPN (bất kể qua WiFi hoặc Cellular), mã trước đó sẽ không thành công. Bây giờ, nó hoạt động ngay cả với các kết nối VPN. Kết nối VPN được ưu tiên hơn WiFi và Cell vì đó là cách thiết bị xử lý nó. Điều này thậm chí sẽ hoạt động cho máy Mac vì kết nối VPN trên máy Mac cũng đang sử dụng IF utun0 nhưng chưa được thử nghiệm.
EDIT3: (9/8/2016) Với các vấn đề mà @Qiulang (xem bình luận) gặp phải với mã VPN (mà người khác đã thêm), tôi đã nhận xét nó. Nếu bất cứ ai biết chắc chắn làm thế nào để chỉ định VPN người dùng, vui lòng bấm nút bình luận.
addr
được NULL? người dùng của tôi thỉnh thoảng nhận được NULL. Bạn có biết những lý do có thể?
AF_INET
để kiểm tra. có thể là cái này?
Trong tệp thực hiện của bạn .m,
#import <ifaddrs.h>
#import <arpa/inet.h>
// Get IP Address
- (NSString *)getIPAddress {
NSString *address = @"error";
struct ifaddrs *interfaces = NULL;
struct ifaddrs *temp_addr = NULL;
int success = 0;
// retrieve the current interfaces - returns 0 on success
success = getifaddrs(&interfaces);
if (success == 0) {
// Loop through linked list of interfaces
temp_addr = interfaces;
while(temp_addr != NULL) {
if(temp_addr->ifa_addr->sa_family == AF_INET) {
// Check if interface is en0 which is the wifi connection on the iPhone
if([[NSString stringWithUTF8String:temp_addr->ifa_name] isEqualToString:@"en0"]) {
// Get NSString from C String
address = [NSString stringWithUTF8String:inet_ntoa(((struct sockaddr_in *)temp_addr->ifa_addr)->sin_addr)];
}
}
temp_addr = temp_addr->ifa_next;
}
}
// Free memory
freeifaddrs(interfaces);
return address;
}
Nhiều giải pháp hiện tại chỉ xem xét các giao diện không dây, sẽ không hoạt động đối với các kết nối có dây thông qua bộ điều hợp Ethernet (tức là không có Wifi hoặc 3G); xem giải pháp mới hơn này xem xét các địa chỉ IP thu được thông qua giao diện có dây.
iPad: Cách nhận địa chỉ IP được lập trình WIRED (không qua mạng không dây)
Nhận địa chỉ IP bằng Swift 3:
func getIPAddress() -> String {
var address: String = "error"
var interfaces: ifaddrs? = nil
var temp_addr: ifaddrs? = nil
var success: Int = 0
// retrieve the current interfaces - returns 0 on success
success = getifaddrs(interfaces)
if success == 0 {
// Loop through linked list of interfaces
temp_addr = interfaces
while temp_addr != nil {
if temp_addr?.ifa_addr?.sa_family == AF_INET {
// Check if interface is en0 which is the wifi connection on the iPhone
if (String(utf8String: temp_addr?.ifa_name) == "en0") {
// Get NSString from C String
address = String(utf8String: inet_ntoa((temp_addr?.ifa_addr as? sockaddr_in)?.sin_addr))
}
}
temp_addr = temp_addr?.ifa_next
}
}
// Free memory
freeifaddrs(interfaces)
return address
}
Giải pháp hiện tại không trả về thiết bị en0 trên OS X, đoạn mã sau sử dụng Khung cấu hình hệ thống để nhận các giao diện sau đó sử dụng các hàm C tiêu chuẩn để lấy địa chỉ IP.
#include <stdio.h>
#include <string.h>
#include <sys/socket.h>
#include <arpa/inet.h>
#include <netdb.h>
#include <sys/ioctl.h>
#include <net/if.h>
#define IFT_ETHER 0x6
#include <SystemConfiguration/SCDynamicStore.h>
+(void)getInterfaces
{
SCDynamicStoreRef storeRef = SCDynamicStoreCreate(NULL, (CFStringRef)@"FindCurrentInterfaceIpMac", NULL, NULL);
CFPropertyListRef global = SCDynamicStoreCopyValue (storeRef,CFSTR("State:/Network/Interface"));
id primaryInterface = [(__bridge NSDictionary *)global valueForKey:@"Interfaces"];
for (NSString* item in primaryInterface)
{
if(get_iface_address([item UTF8String]))
{
NSString *ip = [NSString stringWithUTF8String:get_iface_address([item UTF8String])];
NSLog(@"interface: %@ - %@",item,ip);
} else
NSLog(@"interface: %@",item);
}
}
static char * get_iface_address (char *interface)
{
int sock;
uint32_t ip;
struct ifreq ifr;
char *val;
if (!interface)
return NULL;
/* determine UDN according to MAC address */
sock = socket (AF_INET, SOCK_STREAM, 0);
if (sock < 0)
{
perror ("socket");
return NULL;
}
strcpy (ifr.ifr_name, interface);
ifr.ifr_addr.sa_family = AF_INET;
if (ioctl (sock, SIOCGIFADDR, &ifr) < 0)
{
perror ("ioctl");
close (sock);
return NULL;
}
val = (char *) malloc (16 * sizeof (char));
ip = ((struct sockaddr_in *) &ifr.ifr_addr)->sin_addr.s_addr;
ip = ntohl (ip);
sprintf (val, "%d.%d.%d.%d",
(ip >> 24) & 0xFF, (ip >> 16) & 0xFF, (ip >> 8) & 0xFF, ip & 0xFF);
close (sock);
return val;
}
Câu trả lời này được lấy cảm hứng từ câu trả lời của @ DavidH. Tôi đã sửa một số vấn đề, thay thế inet_ntop
bằng cách getnameinfo
cho phép một cách tiếp cận sạch hơn. Lưu ý rằng điều này mang lại một từ điển ánh xạ tên giao diện thành một mảng địa chỉ IP (một giao diện có thể có nhiều IPv4 và IPv6 được liên kết với nó, về mặt kỹ thuật). Nó không phân biệt giữa IPv4 và IPv6:
// Get all our interface addresses.
struct ifaddrs *ifAddresses;
if (getifaddrs( &ifAddresses ) != 0) {
NSLog( @"Couldn't get interface addresses: %d", errno );
return nil;
}
int error;
char host[MAX( INET_ADDRSTRLEN, INET6_ADDRSTRLEN )];
_ipAddressesByInterface = [NSMutableDictionary dictionaryWithCapacity:8];
for (struct ifaddrs *ifAddress = ifAddresses; ifAddress; ifAddress = ifAddress->ifa_next) {
if (!(ifAddress->ifa_flags & IFF_UP) || (ifAddress->ifa_flags & IFF_LOOPBACK))
// Ignore interfaces that aren't up and loopback interfaces.
continue;
if (ifAddress->ifa_addr->sa_family != AF_INET && ifAddress->ifa_addr->sa_family != AF_INET6)
// Ignore non-internet addresses.
continue;
if ((error = getnameinfo( ifAddress->ifa_addr, ifAddress->ifa_addr->sa_len, host, sizeof( host ), NULL, 0, NI_NUMERICHOST )) != noErr) {
// Couldn't to format host name for this address.
NSLog( @"Couldn't resolve host name for address: %s", gai_strerror( error ) );
continue;
}
NSString *ifName = [NSString stringWithCString:ifAddress->ifa_name encoding: NSUTF8StringEncoding];
NSMutableArray *ifIpAddresses = _ipAddressesByInterface[ifName];
if (!ifIpAddresses)
ifIpAddresses = _ipAddressesByInterface[ifName] = [NSMutableArray arrayWithCapacity:2];
[ifIpAddresses addObject:[NSString stringWithCString:host encoding: NSUTF8StringEncoding]];
}
freeifaddrs( ifAddresses );
return _ipAddressesByInterface;
strf
- đó có phải là một hàm trợ giúp mà bạn có trong mã của mình không?
err
và strf
. Bạn chỉ có thể thay thế strf
bằng -stringWithCString:encoding:
. err
là một NSLog
trình bao bọc cũng xuất ra tệp & dòng. github.com/Lyndir/Pearl/blob/master/Pearl/ Khăn
Câu trả lời của DavidH hoạt động tốt cho đến khi tôi nhận được kết quả này từ một số mạng di động 4G:
{
"lo0/ipv4" = "127.0.0.1";
"lo0/ipv6" = "fe80::1";
"pdp_ip0/ipv4" = "10.132.76.168";
"utun0/ipv6" = "fe80::72c3:e25e:da85:b730";
}
Tôi không sử dụng vpn vì vậy tôi không biết tại sao tôi lại có utun0 / ipv6.
--- Đã cập nhật ---
Tôi tiếp tục gỡ lỗi vấn đề này và thấy rằng tôi có thể nhận được địa chỉ vpn giả ngay cả trong các mạng 4G khác (đây có phải là lỗi iOS không ??),
{
""awdl0/ipv6"" = ""fe80::c018:9fff:feb2:988"";
""en0/ipv6"" = ""fe80::181a:2e43:f91b:db2b"";
""lo0/ipv4"" = ""127.0.0.1"";
""lo0/ipv6"" = ""fe80::1"";
""pdp_ip0/ipv4"" = ""10.48.10.210"";
""utun0/ipv4"" = ""192.168.99.2"";
}
Nếu tôi đã sử dụng vpn, tôi sẽ nhận được điều này:
{
"lo0/ipv4" = "127.0.0.1";
"lo0/ipv6" = "fe80::1";
"pdp_ip0/ipv4" = "10.49.187.23";
"utun0/ipv6" = "fe80::5748:5b5d:2bf0:658d";
"utun1/ipv4" = "192.168.99.2"; //the real one
}
Vì vậy, đó là utun1 KHÔNG utun0
Không cần tìm hiểu tại sao tôi sẽ phải bỏ kiểm tra vpn :(
---- cập nhật ----
Tôi đã đưa ra một lỗi (28131847) cho apple và trả lời "Không phải tất cả các giao diện utun đều dành cho VPN. Có những tính năng hệ điều hành khác sử dụng giao diện utun."
Nhưng khi tôi hỏi làm thế nào để có được địa chỉ IP vpn hợp lệ thì câu trả lời của họ khá thất vọng, "Bạn có thể vào Cài đặt -> VPN và xem cấu hình VPN của bạn để xem VPN có hoạt động không. Trong một số trường hợp, bạn có thể thấy cũng đã gán địa chỉ IP ở đó. Chúng tôi hiện đang đóng báo cáo lỗi này. " :
---- cập nhật 2016/11/04 ----
Tôi lại gặp sự cố và tôi cần sửa đổi thêm câu trả lời của @ DavidH để khắc phục:
Tôi đã ở trong mạng 4G và tôi đã nhận được địa chỉ này:
addresses: {
"awdl0/ipv6" = "fe80::98fd:e6ff:fea9:3afd";
"en0/ipv6" = "fe80::8dd:7d92:4159:170e";
"lo0/ipv4" = "127.0.0.1";
"lo0/ipv6" = "fe80::1";
"pdp_ip0/ipv4" = "10.37.212.102";
"utun0/ipv6" = "fe80::279c:ea56:a2ef:d128";
}
Với câu trả lời ban đầu của anh ấy, tôi sẽ nhận được IP wifi8080: 8dd: 7d92: 4159: 170e, đó là giả và kết nối không thành công.
Vì vậy, tôi đã sửa đổi mã để thích,
[searchArray enumerateObjectsUsingBlock:^(NSString *key, NSUInteger idx, BOOL *stop)
{
if ((internetReach.isReachableViaWiFi && [key hasPrefix:IOS_WIFI]) ||
(internetReach.isReachableViaWWAN && [key hasPrefix:IOS_CELLULAR])) {
address = addresses[key];
if(address) *stop = YES;
}
} ];
Giải pháp tuyệt vời cho swift trong tập tin này phục vụ tất cả các chi tiết.
Trong một trong những ứng dụng của tôi, tôi cần tìm nạp địa chỉ IP wifi. Tôi đã sử dụng câu trả lời ở trên, trong swift 3 như thế này:
let WIFI_IF = "en0"
let UNKNOWN_IP_ADDRESS = ""
var addresses: [AnyHashable: Any] = ["wireless": UNKNOWN_IP_ADDRESS, "wired": UNKNOWN_IP_ADDRESS, "cell": UNKNOWN_IP_ADDRESS]
var interfaces: UnsafeMutablePointer<ifaddrs>? = nil
var temp_addr: UnsafeMutablePointer<ifaddrs>? = nil
var success: Int = 0
success = Int(getifaddrs(&interfaces))
if success == 0 {
temp_addr = interfaces
while temp_addr != nil {
if temp_addr?.pointee.ifa_addr == nil {
continue
}
if temp_addr?.pointee.ifa_addr.pointee.sa_family == UInt8(AF_INET) {
if (String(utf8String: (temp_addr?.pointee.ifa_name)!) == WIFI_IF) {
addresses["wireless"] = String(utf8String: inet_ntoa(((temp_addr?.pointee.ifa_addr as? sockaddr_in)?.sin_addr)!))
}
}
temp_addr = temp_addr?.pointee.ifa_next
}
}
Trong mã này, Nó gặp sự cố vì tôi phải kiểm tra nil
trong mỗi câu lệnh tôi đã sử dụng làm tùy chọn ?
. Vì vậy, tốt hơn là tôi sử dụng tệp được liên kết nhất định trong lớp của mình. Bây giờ nó trở nên dễ dàng để tôi kiểm tra như:
class func getWifiIPAddress() -> String {
var wifiIp = ""
let WIFI_IF = "en0"
let allInterface = Interface.allInterfaces()
for interf in allInterface {
if interf.name == WIFI_IF {
if let address = interf.address {
if address.contains(".") {
wifiIp = address
break
}
}
}
}
return wifiIp
}
Tôi đã phân tích chuỗi "."
vì lớp Giao diện trả về hai giao diện trong iPhone của tôi cho en0
địa chỉ như "fb00 ::" và địa chỉ như "101.10.1.1"
Tôi đã tạo một tập tin đơn giản để lấy địa chỉ IP. Tôi dựa trên giải pháp này dựa trên câu trả lời của @ lundhjem, @ DavidH và @ Ihunath. Nó xem xét các kết nối có dây. Tôi chưa bao gồm VPN trong giải pháp này.
PCNetwork.h
#import <Foundation/Foundation.h>
NS_ASSUME_NONNULL_BEGIN
@interface PCNetwork : NSObject
+ (NSString *)getIPAddress; // Prefers IPv4
+ (NSString *)getIPAddress:(BOOL)preferIPv4;
+ (NSDictionary *)getIPAddresses;
@end
NS_ASSUME_NONNULL_END
PCNetwork.m
#import "PCNetwork.h"
#include <ifaddrs.h>
#include <arpa/inet.h>
#include <net/if.h>
#define IP_UNKNOWN @"0.0.0.0"
#define IP_ADDR_IPv4 @"ipv4"
#define IP_ADDR_IPv6 @"ipv6"
@implementation PCNetwork
#pragma mark - IP
+ (NSString *)getIPAddress {
return [self getIPAddress:YES];
}
+ (NSString *)getIPAddress:(BOOL)preferIPv4 {
NSArray *searchArray = [self getAllIFSearchArray:preferIPv4];
NSDictionary *addresses = [self getIPAddresses];
DLog(@"addresses: %@", addresses);
__block NSString *address = nil;
[searchArray enumerateObjectsUsingBlock:^(NSString *key, NSUInteger idx, BOOL *stop) {
address = addresses[key];
if(address) *stop = YES;
}];
return address ?: IP_UNKNOWN;
}
+ (NSDictionary *)getIPAddresses {
NSMutableDictionary *addresses = [NSMutableDictionary dictionary];
struct ifaddrs *interfaces;
BOOL success = !getifaddrs(&interfaces); // Retrieve the current interfaces : returns 0 on success
if (success) {
struct ifaddrs *temp_interface;
for (temp_interface = interfaces; temp_interface; temp_interface = temp_interface->ifa_next) { // Loop through linked list of interfaces
if (!(temp_interface->ifa_flags & IFF_UP) || (temp_interface->ifa_flags & IFF_LOOPBACK)) { // Ignore interfaces that aren't up and loopback interfaces.
continue;
}
if (!temp_interface->ifa_addr) {
continue;
}
const struct sockaddr_in *temp_addr = (const struct sockaddr_in*)temp_interface->ifa_addr;
if (temp_addr->sin_family == AF_INET || temp_addr->sin_family == AF_INET6) {
char addrBuf[MAX(INET_ADDRSTRLEN, INET6_ADDRSTRLEN)];
NSString *name = [NSString stringWithUTF8String:temp_interface->ifa_name];
NSString *type = nil;
if (temp_addr->sin_family == AF_INET) {
if (inet_ntop(AF_INET, &temp_addr->sin_addr, addrBuf, INET_ADDRSTRLEN)) {
type = IP_ADDR_IPv4;
}
} else {
const struct sockaddr_in6 *addr6 = (const struct sockaddr_in6*)temp_interface->ifa_addr; // AF_INET6
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];
}
}
}
freeifaddrs(interfaces); // Free memory
}
return addresses.count ? addresses.copy : nil;
}
#pragma mark - Inter Frame Spacing
+ (NSArray *)getAllIFSearchArray:(BOOL)preferIPv4 {
NSArray *KNOWN_WIFI_IFS = @[@"en0"];
NSArray *KNOWN_WIRED_IFS = @[@"en1",@"en2",@"en3",@"en4"];
NSArray *KNOWN_CELL_IFS = @[@"pdp_ip0",@"pdp_ip1",@"pdp_ip2",@"pdp_ip3"];
NSMutableArray *searchArray = [NSMutableArray array];
// Add wifi
[searchArray addObjectsFromArray:[self getIFSearchArrayWith:KNOWN_WIFI_IFS preferIPv4:preferIPv4]];
// Add cell
[searchArray addObjectsFromArray:[self getIFSearchArrayWith:KNOWN_CELL_IFS preferIPv4:preferIPv4]];
// Add wired
[searchArray addObjectsFromArray:[self getIFSearchArrayWith:KNOWN_WIRED_IFS preferIPv4:preferIPv4]];
return searchArray.copy;
}
+ (NSArray *)getIFSearchArrayWith:(NSArray *)iFList preferIPv4:(BOOL)preferIPv4 {
NSMutableArray *searchArray = [NSMutableArray array];
for (NSString *iFType in iFList) {
if (preferIPv4) {
[searchArray addObject:[NSString stringWithFormat:@"%@/%@", iFType, IP_ADDR_IPv4]];
[searchArray addObject:[NSString stringWithFormat:@"%@/%@", iFType, IP_ADDR_IPv6]];
} else {
[searchArray addObject:[NSString stringWithFormat:@"%@/%@", iFType, IP_ADDR_IPv6]];
[searchArray addObject:[NSString stringWithFormat:@"%@/%@", iFType, IP_ADDR_IPv4]];
}
}
return searchArray.copy;
}
@end
trong iOS 13.4.1 không hoạt động với tôi. tôi dùng cái này để sửa nó
+ (NSString *)getIPAddress{
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];
__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;
*stop = YES;
}
}else{
if([self isValidatIP:address]) {
*stop = YES;
}
}
} ];
return address ? address : @"error";
}
+ (NSString *)getIPType{
NSString *ipAddress = [self getIPAddress];
if ([self isValidatIP:ipAddress]) {
return @"04";//ipv4
}else{
return @"06";//ipv6
}
}
+ (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;
}
+ (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;
}