Я хотів би отримати IP-адресу свого iPad програмно. Як я можу запитати мережеву підсистему, щоб дізнатися, що таке мої IPv4 (та IPv6) адреси?
PS: Чи можна якось відключити IPv6?
Я хотів би отримати IP-адресу свого iPad програмно. Як я можу запитати мережеву підсистему, щоб дізнатися, що таке мої IPv4 (та IPv6) адреси?
PS: Чи можна якось відключити IPv6?
Відповіді:
У наведеному нижче коді знаходяться всі адреси IPv4 та IPv6 на пристрої iOS або OSX. Перший getIPAddress
метод діє у більшій чи меншій мірі, як і старший код у цій відповіді: ви можете віддати перевагу одній або іншій адресі типу, і він завжди віддає перевагу WIFI над стільниковим (очевидно, ви могли це змінити).
Що ще цікавіше, він може повернути словник усіх знайдених адрес, пропускаючи адреси для not up
інтерфейсів або адреси, пов'язані з loopback
. Попередній код, а також інші рішення на цю тему не будуть правильно декодувати IPv6 (inet_ntoa не може з ними боротися). На це вказував мені Йенс Альфке на форумі Apple - належна функція використання inet_ntop (подивіться на сторінку man, або зверніться до цієї статті inet_ntop, яку також надає Jens.
Клавіші словника мають форму "інтерфейс" "/" "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: Код оновлено 16 травня 2014 року (помилка, яку вказав lhunath, див. Коментарі). Зараз повернулися петлі, але ви легко скасуєте тест, щоб виключити їх самостійно.
EDIT2: (якоюсь невідомою особою): Удосконалено далі 13 березня 2015 року: Якщо користувач використовує VPN (незалежно від WiFi або Cellular), попередній код не вдався б. Тепер він працює навіть з VPN-підключеннями. VPN-з'єднання мають перевагу над WiFi та Cell, тому що таким чином обробляє пристрій. Це навіть повинно працювати для Macs, оскільки підключення VPN на Mac також використовує IF utun0, але не перевірено.
EDIT3: (8.09.2016) Враховуючи проблеми, які виникли у @Qiulang (див. Коментарі) з кодом VPN (який хтось ще додав), я прокоментував це. Якщо хтось точно знає, як вказати 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;
}
У багатьох існуючих рішеннях розглядаються лише бездротові інтерфейси, які не працюватимуть для дротових з'єднань через адаптер Ethernet (тобто немає Wi-Fi або 3G); див. це нещодавнє рішення, яке також розглядає IP-адреси, отримані через дротові інтерфейси.
iPad: як отримати IP-адресу програмно WIRED (не через бездротовий зв’язок)
Отримати IP-адресу за допомогою 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
}
Поточне рішення не повертає пристрій en0 в OS X, наступний код використовує Framework Configuration Framework для отримання інтерфейсів, а потім використовує стандартні функції 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.
--- оновлено ---
Далі я налагодив цю проблему і виявив, що я можу отримати підроблену адресу vpn навіть у інших мережах 4G (це помилка 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
}
Так це utun1 НЕ utun0
Не розуміючи, чому мені просто доведеться скинути vpn check :(
---- оновлення ----
Я підняв помилку (28131847) до apple і відповів "Не всі інтерфейси utun призначені для VPN. Є інші функції ОС, які використовують інтерфейси utun".
Але коли я запитав, як отримати дійсну IP-адресу vpn тоді, їх відповідь була досить розчарована: "Ви можете зайти в Налаштування -> 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;
}
} ];
Прекрасне рішення для швидкого використання у цьому файлі, який обслуговує всі деталі.
В одному зі своїх додатків мені потрібно отримати IP-адресу Wi-Fi. Я використовував відповіді вище, у швидкому 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
}
Я проаналізував рядок, "."
тому що клас інтерфейсів повертає два інтерфейси в моєму iPhone за en0
адресою "fb00 ::" та адресою типу "101.10.1.1"
Я створив простий файл для отримання 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;
}