프로그래밍 방식으로 내 iPad의 IP 주소를 얻고 싶습니다. 내 IPv4 (및 IPv6) 주소가 무엇인지 확인하기 위해 네트워킹 하위 시스템을 쿼리하려면 어떻게해야합니까?
PS : 어떻게 든 IPv6를 비활성화 할 수 있습니까?
프로그래밍 방식으로 내 iPad의 IP 주소를 얻고 싶습니다. 내 IPv4 (및 IPv6) 주소가 무엇인지 확인하기 위해 네트워킹 하위 시스템을 쿼리하려면 어떻게해야합니까?
PS : 어떻게 든 IPv6를 비활성화 할 수 있습니까?
답변:
다음 코드는 iOS 또는 OSX 장치에서 모든 IPv4 및 IPv6 주소를 찾습니다. 첫 번째 getIPAddress
방법은이 답변의 이전 코드처럼 다소간 작동합니다. 하나 또는 다른 유형의 주소를 선호 할 수 있으며 항상 셀룰러보다 WIFI를 선호합니다 (분명히 이것을 변경할 수 있음).
더 흥미롭게도 발견 된 모든 주소의 사전을 반환하고 not up
인터페이스의 주소를 건너 뛰 거나와 관련된 주소를 반환 할 수 있습니다 loopback
. 이 주제에 대한 이전 코드와 다른 솔루션은 IPv6를 올바르게 디코딩하지 않습니다 (inet_ntoa는이를 처리 할 수 없습니다). 이것은 Apple 포럼에서 Jens Alfke 가 저에게 지적했습니다 . 적절한 기능은 inet_ntop입니다 (맨 페이지를 보거나 Jens가 제공하는 이 inet_ntop 기사를 참조하십시오 .
사전 키의 형식은 "interface" "/" "ipv4 또는 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 : 코드가 2014 년 5 월 16 일에 업데이트되었습니다 (Lhunath가 지적한 버그, 주석 참조). 이제 루프백 주소가 반환되었지만 테스트의 주석 처리를 제거하여 직접 제외 할 수 있습니다.
EDIT2 : (알 수없는 사람에 의해) : 2015 년 3 월 13 일 추가 개선 : 사용자가 VPN을 사용하는 경우 (WiFi 또는 셀룰러를 통해) 이전 코드가 실패했을 것입니다. 이제 VPN 연결에서도 작동합니다. VPN 연결은 장치가 처리하는 방식이므로 WiFi 및 셀보다 우선합니다. Mac의 VPN 연결도 IF utun0을 사용하지만 테스트되지 않았기 때문에 Mac에서도 작동합니다.
EDIT3 : (2016 년 9 월 8 일) VPN 코드 (다른 사람이 추가 한)로 @Qiulang (댓글 참조)이 경험 한 문제를 감안할 때 주석 처리했습니다. 사용자 VPN을 지정하는 방법을 확실히 아는 사람이 있으면 댓글을 달아주세요.
addr
NULL을 얻습니까? 내 사용자는 때때로 NULL을 얻습니다. 가능한 이유가 무엇인지 알고 있습니까?
AF_INET
확인 용도로만 사용 하고 있습니다. 이것이 될 수 있습니까?
구현 파일 .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;
}
기존의 많은 솔루션은 이더넷 어댑터 (예 : Wi-Fi 또는 3G 없음)를 통한 유선 연결에는 작동하지 않는 무선 인터페이스 만 고려합니다. 유선 인터페이스를 통해 얻은 IP 주소도 고려하는이 최신 솔루션을 참조하십시오.
Swift 3을 사용하여 IP 주소 가져 오기 :
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
}
현재 솔루션은 OS X에서 en0 장치를 반환하지 않습니다. 다음 코드는 시스템 구성 프레임 워크를 사용하여 인터페이스를 가져온 다음 표준 C 함수를 사용하여 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;
}
이 답변은 @DavidH의 답변에서 영감을 얻었습니다. 나는 몇 가지 문제를 해결 교체 inet_ntop
와 함께 getnameinfo
하는 깨끗한 접근 할 수 있습니다. 이렇게하면 인터페이스 이름을 IP 주소 배열에 매핑하는 사전이 생성됩니다 (인터페이스에는 기술적으로 여러 IPv4 및 IPv6가 연결될 수 있음). IPv4와 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
-그것이 당신의 코드에있는 도우미 함수인가?
err
및 strf
. 당신은 대체 할 수 있습니다 strf
로 -stringWithCString:encoding:
. 파일 및 라인도 출력 err
하는 NSLog
래퍼입니다. github.com/Lyndir/Pearl/blob/master/Pearl/…
@DavidH의 답변은 일부 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";
}
나는 vpn을 사용하지 않기 때문에 왜 utun0 / ipv6을 사용했는지 모르겠습니다.
--- 업데이트 됨 ---
이 문제를 추가로 디버깅하고 다른 4G 네트워크에서도 가짜 VPN 주소를 얻을 수 있음을 발견했습니다 (이 iOS 버그입니까 ??).
{
""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"";
}
내가 vpn을 사용했다면 나는 이것을 얻을 것이다 :
{
"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
}
따라서 utun0이 아닌 utun1입니다.
왜 VPN 검사를 중단해야하는지 알지 못하고 :(
---- 업데이트 ----
Apple에 버그 (28131847)를 제기하고 "모든 utun 인터페이스가 VPN 용은 아닙니다. utun 인터페이스를 사용하는 다른 OS 기능이 있습니다."라고 답했습니다.
그러나 내가 유효한 VPN IP 주소를 얻는 방법을 물었을 때, 그들의 대답은 다소 실망 스러웠습니다. "설정-> VPN으로 이동하여 VPN 구성을 확인하여 VPN이 활성 상태인지 확인할 수 있습니다. 어떤 경우에는 다음을 볼 수 있습니다. 할당 된 IP 주소도 있습니다. 이제이 버그 보고서를 종료합니다. " :(
---- 2016/11/04 업데이트 ----
문제가 다시 발생하고 문제를 해결하기 위해 @DavidH의 답변을 추가로 수정해야합니다.
나는 4G 네트워크에 있었고 다음 주소를 얻었습니다.
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";
}
그의 원래 답변으로 나는 가짜이고 연결이 실패한 wifi IP fe80 :: 8dd : 7d92 : 4159 : 170e를 얻을 것입니다.
그래서 코드를 좋아하도록 수정했습니다.
[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;
}
} ];
모든 세부 정보를 제공하는 이 파일의 신속한 솔루션입니다 .
내 앱 중 하나에서 Wi-Fi IP 주소를 가져와야합니다. 위의 답변을 다음과 같이 신속한 3에서 사용했습니다.
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
}
}
이 코드에서는 nil
선택 사항으로 사용한 각 문 을 확인해야하기 때문에 충돌 ?
합니다. 그래서 수업에서 주어진 링크 파일을 사용하는 것이 좋습니다. 이제 다음과 같이 쉽게 확인할 수 있습니다.
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
}
"."
인터페이스 클래스가 en0
"fb00 ::"과 같은 주소와 "101.10.1.1"과 같은 주소에 대해 내 iPhone에서 두 개의 인터페이스를 반환 하기 때문에 문자열을 구문 분석 했습니다.
IP 주소를 얻기위한 간단한 파일을 만들었습니다. 이 솔루션은 @ lundhjem, @DavidH 및 @Ihunath의 답변을 기반으로합니다. 유선 연결을 고려합니다. 하지만이 솔루션에 VPN을 포함하지 않았습니다.
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
iOS 13.4.1에서는 나를 위해 작동하지 않습니다. 이 수정을 사용합니다.
+ (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;
}