मैं अपने iPad का IP पता प्रोग्रामेटिक रूप से प्राप्त करना चाहूंगा। मैं अपने आईपीवी 4 (और आईपीवी 6) पते क्या हैं, यह जानने के लिए मैं नेटवर्किंग सबसिस्टम की क्वेरी कैसे कर सकता हूं?
पुनश्च: क्या मैं किसी भी तरह आईपीवी 6 को निष्क्रिय कर सकता हूं?
मैं अपने iPad का IP पता प्रोग्रामेटिक रूप से प्राप्त करना चाहूंगा। मैं अपने आईपीवी 4 (और आईपीवी 6) पते क्या हैं, यह जानने के लिए मैं नेटवर्किंग सबसिस्टम की क्वेरी कैसे कर सकता हूं?
पुनश्च: क्या मैं किसी भी तरह आईपीवी 6 को निष्क्रिय कर सकता हूं?
जवाबों:
निम्नलिखित कोड एक iOS या OSX डिवाइस पर सभी IPv4 और IPv6 पतों को खोजता है। पहली getIPAddress
विधि इस उत्तर में पुराने कोड के रूप में अधिक या कम कार्य करती है: आप या तो एक या दूसरे प्रकार के पते को पसंद कर सकते हैं, और यह हमेशा सेलुलर पर वाईफ़ाई को प्राथमिकता देता है (जाहिर है कि आप इसे बदल सकते हैं)।
अधिक दिलचस्प बात यह है कि इसमें पाए गए सभी पतों का एक शब्दकोश लौट सकता है, not up
इंटरफेस के लिए पतों को छोड़ना, या इससे जुड़े पते loopback
। पिछले कोड के साथ-साथ इस विषय पर अन्य समाधान IPv6 को ठीक से डिकोड नहीं करेंगे (inet_ntoa उनसे निपट नहीं सकते)। यह जेन्स अल्फके द्वारा एक Apple फोरम पर मुझे बताया गया था - उपयोग करने के लिए उचित कार्य inet_ntop है (मैन पेज देखें, और जेन्स द्वारा प्रदान किए गए इस inet_ntop लेख को देखें) ।
शब्दकोश कुंजियों में "इंटरफ़ेस" "/" "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 को अपडेट किया गया (बग को लुनथ द्वारा इंगित किया गया, टिप्पणियां देखें)। लूपबैक पते अब वापस आ गए हैं, लेकिन आपके लिए यह आसान है कि आप उन्हें बाहर करने के लिए परीक्षण को अनसुना कर दें।
EDIT2: (कुछ अज्ञात व्यक्ति द्वारा): 13 मार्च, 2015 को और बेहतर बनाया गया: यदि उपयोगकर्ता वीपीएन (वाईफाई या सेलुलर की तुलना में) का उपयोग करता है, तो पिछला कोड विफल हो जाता। अब, यह वीपीएन कनेक्शन के साथ भी काम करता है। वीपीएन कनेक्शनों को वाईफाई और सेल पर प्राथमिकता दी जाती है, क्योंकि डिवाइस इसे संभालता है। यह भी मैक के लिए काम करना चाहिए क्योंकि एक मैक पर वीपीएन कनेक्शन भी IF ut00 का उपयोग कर रहा है लेकिन परीक्षण नहीं किया गया है।
EDIT3: (9/8/2016) वीपीएन कोड (जो किसी और को जोड़ा गया) के साथ @Qiulang (टिप्पणियों को देखें) द्वारा अनुभव की गई समस्याओं को देखते हुए, मैंने इसे टिप्पणी की है। अगर किसी को निश्चित रूप से पता है कि उपयोगकर्ता वीपीएन कैसे निर्दिष्ट करें तो कृपया टिप्पणी के साथ झंकार करें।
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;
}
कई मौजूदा समाधान केवल वायरलेस इंटरफेस पर विचार करते हैं, जो एक ईथरनेट एडाप्टर (यानी। कोई वाईफ़ाई या 3 जी) के माध्यम से वायर्ड कनेक्शन के लिए काम नहीं करेगा; इस हालिया समाधान को देखें जो वायर्ड इंटरफेस के माध्यम से प्राप्त आईपी पते पर भी विचार करता है।
स्विफ्ट 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
}
वर्तमान समाधान OS X पर en0 डिवाइस को वापस नहीं करता है, निम्न कोड इंटरफेस प्राप्त करने के लिए सिस्टम कॉन्फ़िगरेशन फ्रेमवर्क का उपयोग करता है फिर आईपी पते को प्राप्त करने के लिए मानक सी फ़ंक्शन का उपयोग करता है।
#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;
}
यह उत्तर @ डेविड के उत्तर से प्रेरित था। मैंने कुछ मुद्दों को तय किया, जिनके 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/…
@ डेविड का जवाब तब तक ठीक काम करता है जब तक मुझे यह परिणाम कुछ 4 जी सेलुलर नेटवर्क से नहीं मिला:
{
"lo0/ipv4" = "127.0.0.1";
"lo0/ipv6" = "fe80::1";
"pdp_ip0/ipv4" = "10.132.76.168";
"utun0/ipv6" = "fe80::72c3:e25e:da85:b730";
}
मैं वीपीएन का उपयोग नहीं कर रहा हूं इसलिए मुझे पता नहीं है कि मेरे पास 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
}
तो यह utun1 नहीं utun0 है
यह पता लगाने के बिना कि मुझे सिर्फ वीपीएन चेक गिराना होगा :(
---- अपडेट करें ----
मैंने एक बग (28131847) सेब के लिए उठाया और उत्तर दिया "वीपीएन के लिए सभी यूट्यून इंटरफेस नहीं हैं। अन्य ओएस फीचर्स हैं जो यूट्यून इंटरफेस का उपयोग करते हैं।"
लेकिन जब मैंने पूछा कि वैध वीपीएन आईपी पता कैसे प्राप्त किया जाए, तो उनका जवाब निराश था, "आप सेटिंग्स में जा सकते हैं -> वीपीएन और अपने वीपीएन कॉन्फ़िगरेशन को देखने के लिए देखें कि क्या वीपीएन सक्रिय है। कुछ मामलों में आप देख सकते हैं। वहां भी आईपी एड्रेस सौंपा गया है। हम अब इस बग रिपोर्ट को बंद कर रहे हैं। " :(
---- अद्यतन 2016/11/04 ----
मैंने समस्या को फिर से मारा और मुझे इसे ठीक करने के लिए @ डेविड के जवाब को और संशोधित करने की आवश्यकता है:
मैं 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;
}
} ];
इस फ़ाइल में स्विफ्ट के लिए बढ़िया समाधान जो सभी विवरणों को प्रस्तुत करता है।
मेरे एक ऐप में मुझे वाईफाई आईपी एड्रेस लाना है। मैंने ऊपर दिए गए उत्तरों का उपयोग किया है, जैसे स्विफ्ट 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" जैसे पते के लिए दो इंटरफ़ेस देता है।
मैंने आईपी एड्रेस प्राप्त करने के लिए एक साधारण फाइल बनाई। मैंने इस समाधान को @ lundhjem's, @ DavidH's और @ Ihunath के उत्तरों पर आधारित किया। यह वायर्ड कनेक्शन पर विचार करता है। मैंने हालांकि इस समाधान में वीपीएन को शामिल नहीं किया है।
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;
}