आईओएस / मैकओएस पर प्रोग्रामिक रूप से अपना आईपी पता कैसे प्राप्त करें?


124

मैं अपने iPad का IP पता प्रोग्रामेटिक रूप से प्राप्त करना चाहूंगा। मैं अपने आईपीवी 4 (और आईपीवी 6) पते क्या हैं, यह जानने के लिए मैं नेटवर्किंग सबसिस्टम की क्वेरी कैसे कर सकता हूं?

पुनश्च: क्या मैं किसी भी तरह आईपीवी 6 को निष्क्रिय कर सकता हूं?


14
उपरोक्त आपके 'पीएस' के संबंध में, कृपया किसी के डिवाइस पर IPv6 को प्रोग्रामेटिक रूप से अक्षम न करें। यह सिर्फ सादा असभ्य है।
जेरेमी विज़सर

आप IPv6 को अक्षम नहीं कर सकते। यह जरूरी है। वास्तव में, आपके iOS ऐप को IPv6 का समर्थन करना चाहिए।
माइकल हैम्पटन

जवाबों:


132

निम्नलिखित कोड एक 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 (टिप्पणियों को देखें) द्वारा अनुभव की गई समस्याओं को देखते हुए, मैंने इसे टिप्पणी की है। अगर किसी को निश्चित रूप से पता है कि उपयोगकर्ता वीपीएन कैसे निर्दिष्ट करें तो कृपया टिप्पणी के साथ झंकार करें।


कितनी बार addrNULL मिलता है? मेरे उपयोगकर्ताओं को कभी-कभी NULL मिलता है। क्या आप जानते हैं कि संभावित कारण क्या हैं?
हेल्मीबी

मैं केवल AF_INETजाँच के लिए उपयोग कर रहा हूँ । यह हो सकता है?
हेल्मीबी

1
मुझे नहीं पता, लेकिन यह सुनिश्चित करने के लिए है कि आपके उपयोगकर्ता IPV6 नेटवर्क पर हो सकते हैं।
डेविड एच

2
यह "सही" उत्तर होना चाहिए क्योंकि यह 3 जी के साथ पूरा हो गया है। अद्यतन के लिए धन्यवाद।
पामे

1
मुझे नहीं लगता कि यह IPv6 के साथ सही ढंग से काम करता है। Inet_ntoa फ़ंक्शन एक IPv4 पता लेता है, इसलिए मामले में जहां sa_type == AF_INET6, आप IPv6 पता ले रहे हैं और इसे IPv4 टाइप कर रहे हैं और इसे स्ट्रिंग में बदल रहे हैं (मूल रूप से 128-बिट के उच्च 32 बिट्स से) पता।)
जेन अल्फके

88

आपकी कार्यान्वयन फ़ाइल में .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;

} 

1
इंटरफ़ेस सूची में कोई en0 इंटरफ़ेस प्रकट नहीं होता है, इसलिए केवल त्रुटि देता है। यकीन नहीं होता कि कुछ बदल गया है, लेकिन निश्चित रूप से मेरे लिए iOS 5.x पर काम नहीं कर रहा है
wuf810

11
यदि आप नीचे देखते हैं तो आपको कुछ थोड़े संशोधित कोड मिलेंगे जो WIFI के बंद होने पर सेल (3G) का पता देता है।
डेविड एच

1
निम्नलिखित कोड केवल en0 का IPv4 पता देता है। IPv6 के बारे में क्या? क्या कोई कोड नमूना दे सकता है कि इसे कैसे पुनः प्राप्त किया जाए?
ऊद रेगेव

2
जब डिवाइस वाईफाई से कनेक्ट नहीं है, लेकिन यह सेल एड्रेस नेटवर्क पर
Mapedd

1
अगर ([[NSString stringWithUTF8String: temp_addr-> ifa_name] isEqualToString: @ "en0"]) से (तो) [(NSString stringWithUTF8String: temp_addr-> ifa_name] isEqual] stringWithUTF8String: temp_addr-> ifa_name] isEqualToString: @ "pdp_ip0"]) आईपी जब डिवाइस वाईफ़ाई से कनेक्ट नहीं .. पाने के लिए
राजू

4

कई मौजूदा समाधान केवल वायरलेस इंटरफेस पर विचार करते हैं, जो एक ईथरनेट एडाप्टर (यानी। कोई वाईफ़ाई या 3 जी) के माध्यम से वायर्ड कनेक्शन के लिए काम नहीं करेगा; इस हालिया समाधान को देखें जो वायर्ड इंटरफेस के माध्यम से प्राप्त आईपी पते पर भी विचार करता है।

iPad: IP पता कैसे प्राप्त करें


अति उत्कृष्ट! मैं इसे जल्द ही अपने कोड में जोड़ने जा रहा हूं। क्या है en1 - क्या आप जानते हैं?
डेविड एच।

1
मैं नहीं करता, लेकिन मैंने नोटिस किया कि यह अन्य एन इंटरफेस की तरह AF_INET परिवार नहीं है
lundhjem

1
@DavidH हाल ही में ईथरनेट IP कुछ iPads पर en1 पर दिखाई दे रहा है, इसलिए ऐसा प्रतीत होता है कि यह कुछ परिदृश्यों में AF_INET परिवार का सदस्य भी है। आपको उस इंटरफ़ेस को भी देखना चाहिए।
लुधिज्म

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
}

1

वर्तमान समाधान 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;
}

अफसोस की बात है, SCDynamicStoreCreate iOS पर उपलब्ध नहीं है, जैसा कि है: SCDynamicStoreCopyValue
एलेक्स ज़ावाटोन

1

यह उत्तर @ डेविड के उत्तर से प्रेरित था। मैंने कुछ मुद्दों को तय किया, जिनके 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/…
lhuath

1

@ डेविड का जवाब तब तक ठीक काम करता है जब तक मुझे यह परिणाम कुछ 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;
     }
 } ];

मैंने वीपीएन समस्या के बारे में आंतरिक मंचों पर पोस्ट किया है, Apple इंजीनियर ने मदद करने की पेशकश की है। मुझे जरूरत है कि आप मुझे मैक डॉट कॉम
डेविड एच

1

इस फ़ाइल में स्विफ्ट के लिए बढ़िया समाधान जो सभी विवरणों को प्रस्तुत करता है।

मेरे एक ऐप में मुझे वाईफाई आईपी एड्रेस लाना है। मैंने ऊपर दिए गए उत्तरों का उपयोग किया है, जैसे स्विफ्ट 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" जैसे पते के लिए दो इंटरफ़ेस देता है।


1
संभावित समाधान का लिंक हमेशा स्वागत योग्य है, लेकिन कृपया लिंक के चारों ओर संदर्भ जोड़ें , ताकि आपके साथी उपयोगकर्ताओं को यह पता चले कि यह क्या है और यह क्यों है। हमेशा एक महत्वपूर्ण लिंक का सबसे प्रासंगिक हिस्सा उद्धृत करें, यदि लक्ष्य साइट उपलब्ध नहीं है या स्थायी रूप से ऑफ़लाइन है। इस बात पर ध्यान दें कि किसी बाहरी साइट की लिंक से मुश्किल से अधिक होना एक संभावित कारण है कि कुछ उत्तरों को क्यों और कैसे हटाया जाता है?
पॉल राउब

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

0

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;
}
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.