আইওএস / ম্যাকোসগুলিতে প্রোগ্রাম হিসাবে আমার আইপি ঠিকানাটি কীভাবে পাবেন?


124

আমি আমার আইপ্যাডের আইপি ঠিকানা প্রোগ্রামগতভাবে পেতে চাই। আমার আইপিভি 4 (এবং আইপিভি 6) ঠিকানাগুলি কী কী তা জানতে আমি কীভাবে নেটওয়ার্কিং সাবসিস্টেমটিকে জিজ্ঞাসা করতে পারি?

PS: আমি কি কোনওভাবে আইপিভি 6 অক্ষম করতে পারি?


14
উপরের আপনার 'পিএস' সম্পর্কিত, দয়া করে কারও ডিভাইসে আইপিভি 6 অক্ষম করবেন না। এটা ঠিক সরল অভদ্র।
জেরেমি ভিজার

আপনি আইপিভি 6 অক্ষম করতে পারবেন না। এটা বাধ্যতামূলক. আসলে, আপনার আইওএস অ্যাপ্লিকেশনটি অবশ্যই আইপিভি 6 সমর্থন করবে।
মাইকেল হ্যাম্পটন

উত্তর:


132

নিম্নলিখিত কোডটি কোনও আইওএস বা ওএসএক্স ডিভাইসে সমস্ত আইপিভি 4 এবং আইপিভি 6 ঠিকানা খুঁজে পায়। প্রথম getIPAddressপদ্ধতিটি এই উত্তরে পুরানো কোড হিসাবে কমবেশি কাজ করে: আপনি এক বা অন্য ধরণের ঠিকানা পছন্দ করতে পারেন এবং এটি সর্বদা সেলুলারের চেয়ে WIFI পছন্দ করে (সম্ভবত আপনি এটি পরিবর্তন করতে পারেন)।

আরও মজার বিষয় হল এটি পাওয়া সমস্ত ঠিকানার একটি অভিধান, not upইন্টারফেসের জন্য ঠিকানাগুলি এড়িয়ে যাওয়া , বা এর সাথে সম্পর্কিত ঠিকানাগুলিতে ফিরে আসতে পারে loopback। পূর্ববর্তী কোড এবং এই বিষয়গুলির অন্যান্য সমাধানগুলি আইপিভি 6 সঠিকভাবে ডিকোড করবে না (inet_ntoa তাদের সাথে ডিল করতে পারে না)। এটি একটি অ্যাপল ফোরামে জেনস আলফকের দ্বারা আমার দিকে ইঙ্গিত করা হয়েছিল - ব্যবহারের সঠিক ফাংশনটি হ'ল 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 আপডেট হয়েছে (বাগ লুনাথ দ্বারা নির্দেশিত, মন্তব্য দেখুন)। লুপব্যাকের ঠিকানাগুলি এখন ফিরে এসেছে, তবে এগুলি নিজে বাদ দিয়ে পরীক্ষার জন্য কোনও অসুবিধা করা আপনার পক্ষে সহজ।

সম্পাদনা 2: (কিছু অজানা ব্যক্তি দ্বারা): 13 মার্চ, 2015 আরও উন্নত: যদি ব্যবহারকারী কোনও ভিপিএন (ওয়াইফাই বা সেলুলার নির্বিশেষে) ব্যবহার করে তবে আগের কোডটি ব্যর্থ হত। এখন এটি ভিপিএন সংযোগ নিয়েও কাজ করে। ভিপিএন সংযোগগুলিকে ওয়াইফাই এবং সেল এর চেয়ে বেশি প্রাধান্য দেওয়া হয় কারণ ডিভাইসটি সেভাবেই এটি পরিচালনা করে। এটি এমনকি ম্যাকদের জন্য কাজ করা উচিত কারণ কোনও ম্যাকের ভিপিএন সংযোগটি যদি আইফ ইউটিউন 0 ব্যবহার করে তবে পরীক্ষিত হয় না।

EDIT3: (9/8/2016) ভিপিএন কোড (যা অন্য কেউ যুক্ত করেছেন) দিয়ে @ কিউলাং (মন্তব্যগুলি দেখুন) দ্বারা প্রাপ্ত সমস্যাগুলি দেখে আমি এ সম্পর্কে মন্তব্য করেছি। যদি কোনও ব্যবহারকারী ভিপিএন কীভাবে নির্দিষ্ট করতে হয় তা যদি কেউ নির্দিষ্টভাবে জানেন তবে দয়া করে একটি মন্তব্য দিয়ে চিমে দিন।


কত ঘন ঘন addrনুল হয়? আমার ব্যবহারকারীরা মাঝে মাঝে NULL পান get আপনি কি সম্ভাব্য কারণ জানেন?
হেলমিবি

আমি শুধুমাত্র AF_INETপরীক্ষা করতে ব্যবহার করছি । এই হতে পারে?
হেলমিবি

1
আমি জানি না, তবে এটি নিশ্চিত যে আপনার ব্যবহারকারীরা আইপিভি 6 নেটওয়ার্কে থাকতে পারেন।
ডেভিড এইচ

2
3 জি সহ এটি সম্পূর্ণ হওয়ায় এটি "সঠিক" উত্তর হওয়া উচিত। আপডেটের জন্য ধন্যবাদ.
পালমে

1
আমি মনে করি না এটি আইপিভি 6 এর সাথে সঠিকভাবে কাজ করে। ইনট_ন্টোয়া ফাংশনটি একটি আইপিভি 4 ঠিকানা গ্রহণ করে, সুতরাং যে ক্ষেত্রে sa_type == AF)ET6, আপনি আইপিভি 6 ঠিকানাটি নিয়ে চলেছেন এবং এটিকে আইপিভি 4-তে টাইপ করে কাস্টিং দিয়ে স্ট্রিংয়ে পরিণত করছেন (মূলত 128-বিটের উচ্চ 32 বিট থেকে ঠিকানা।)
জেনস আলফ্কে

88

আপনার প্রয়োগের ফাইল। মি।

#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
ইন্টারফেস তালিকায় কোনও এন0 ইন্টারফেস উপস্থিত হয় না, সুতরাং কেবল ত্রুটি ফেরায়। কিছু পরিবর্তন হয়েছে কিনা তা নিশ্চিত নয় তবে অবশ্যই আইওএস ৫.x এ আমার জন্য কাজ করছে না
wuf810

11
নীচের দিকে নজর দিলে আপনি কিছুটা সংশোধিত কোড পাবেন যা ডাব্লু ওয়াইফাই বন্ধ থাকলে সেল (3 জি) ঠিকানাটি ফেরত দেয়।
ডেভিড এইচ

1
নিম্নলিখিত কোডটি কেবল en0 এর IPv4 ঠিকানা দেয়। আইপিভি 6 সম্পর্কে কী? কেউ কীভাবে একটি কোড নমুনা এটি পুনরুদ্ধার করতে পারেন?
ওদেড রেগেভ

2
ডিভাইসটি ওয়াইফাইয়ের সাথে সংযুক্ত না থাকলে এই আইপি ঠিকানাটি খুঁজে পায় না, তবে সেলুয়ার নেটওয়ার্কে
ম্যাপেডড

1
নীচের if শর্তটি সংশোধন করুন যদি ([[এনএসএস স্ট্রিং উইথআউটএফএফ স্ট্রিং: টেম্পে_ড্ডার-> আইফএ_নেম] হল একুয়ালটোস্ট্রিং: @ "এন0"]) থেকে স্ট্রিংউইথআউটএফ 8 স্ট্রিং: টেম্পে_ড্রেআর-> আইএফএ_নেম] আইকুয়ালটিস্ট্রিং: @ "পিডিপি_আইপি 0"]) আইপি পাওয়ার জন্য যখন ডিভাইস ওয়াইফাইয়ের সাথে সংযুক্ত থাকে না ..
রাজু

4

অনেক বিদ্যমান সমাধান কেবল ওয়্যারলেস ইন্টারফেস বিবেচনা করে, যা ইথারনেট অ্যাডাপ্টারের মাধ্যমে তারযুক্ত সংযোগগুলির জন্য কাজ করবে না (যেমন কোনও ওয়াইফাই বা 3 জি নয়); এটি আরও সাম্প্রতিক সমাধান দেখুন যা তারযুক্ত ইন্টারফেসের মাধ্যমে প্রাপ্ত আইপি ঠিকানাগুলিকেও বিবেচনা করে।

আইপ্যাড: কীভাবে আইপি অ্যাড্রেস পাবেন প্রোগ্রামিয়ালি ওয়্যারিড (ওয়্যারলেস মাধ্যমে নয়)


অসাধারণ! আমি শীঘ্রই আমার কোডে এটি যুক্ত করতে যাচ্ছি। এন 1 কী - আপনি কি জানেন?
ডেভিড এইচ

1
আমি তা করি না, তবে আমি লক্ষ্য করেছি যে এটি অন্যান্য এন-ইন্টারফেসের মতো এএফপিইটি পরিবারের নয়
লুন্ডজেম

1
@ ডেভিডএইচ সম্প্রতি ইথারনেট আইপি নির্দিষ্ট আইপ্যাডগুলিতে এন 1 এ প্রদর্শিত হচ্ছে, সুতরাং দেখা যাচ্ছে যে এটি কিছু পরিস্থিতিতে দৃশ্যে এএফপিইটি পরিবারের সদস্যও রয়েছে। আপনার সেই ইন্টারফেসটিও পরীক্ষা করা উচিত।
লুন্ডজেম

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

বর্তমান সমাধানটি ওএস এক্স-এ এন0 ডিভাইসটি ফেরত দেয় না, নীচের কোডটি ইন্টারফেসগুলি পেতে সিস্টেম কনফিগারেশন ফ্রেমওয়ার্ক ব্যবহার করে তারপরে আইপি ঠিকানা পাওয়ার জন্য স্ট্যান্ডার্ড সি ফাংশন ব্যবহার করে।

#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;
}

দুঃখের বিষয়, এসসিডিএনমিক স্টোরক্রিয়াটটি আইওএসে অনুপলব্ধ, যেমন: এসসিডিএনমিক স্টোরকপিভ্যালু
অ্যালেক্স জাভাটোন

1

এই উত্তরটি @ ডেভিডএইচ এর উত্তর দ্বারা অনুপ্রাণিত হয়েছিল। আমি কিছু সমস্যা স্থির করেছি, এর সাথে প্রতিস্থাপন inet_ntopকরা হয়েছে getnameinfoযা পরিষ্কারের পদ্ধতির অনুমতি দেয়। নোট করুন যে এটি একটি অভিধান পেয়েছে যা আইপি অ্যাড্রেসের একটি অ্যারেতে একটি ইন্টারফেসের নাম ম্যাপ করে (একটি ইন্টারফেসে প্রযুক্তিগতভাবে একাধিক আইপিভি 4 এবং আইপিভি 6 এর সাথে যুক্ত থাকতে পারে)। এটি 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/…
lhunath

1

@ 4D সেলুলার নেটওয়ার্ক থেকে এই ফলাফল না পাওয়া পর্যন্ত @ ডেভিডএইচ এর উত্তর ঠিক আছে:

{
    "lo0/ipv4" = "127.0.0.1";
    "lo0/ipv6" = "fe80::1";
    "pdp_ip0/ipv4" = "10.132.76.168";
    "utun0/ipv6" = "fe80::72c3:e25e:da85:b730";
}

আমি ভিপিএন ব্যবহার করছি না তাই আমার কেন ইউটিউন 0 / আইপিভি 6 ছিল আমার কোনও ধারণা নেই।

--- আপডেট ---

আমি এই সমস্যাটি আরও ডিবাগ করেছি এবং দেখতে পেয়েছি যে আমি অন্য 4 জি নেটওয়ার্কগুলিতেও এটি একটি নকল ভিপিএন ঠিকানা পেতে পারি (এটি কি আইওএস বাগ আছে ??),

{
    ""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"";
}

আমি ভিপিএন ব্যবহার না করলে আমি এটি পেয়ে যাব:

{
    "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) উত্থাপন করেছি এবং জবাব দিয়েছিলাম "সমস্ত ইউটুন ইন্টারফেস ভিপিএন এর জন্য নয় There অন্যান্য ওএস বৈশিষ্ট্যগুলিও ইউটুন ইন্টারফেস ব্যবহার করে" "

তবে যখন আমি কীভাবে একটি বৈধ ভিপিএন আইপি ঠিকানা পেতে জিজ্ঞাসা করেছি, তখন তাদের উত্তরটি বরং হতাশ হয়েছিল, "আপনি সেটিংসে যেতে পারেন -> ভিপিএন এবং ভিপিএন সক্রিয় আছে কিনা তা দেখতে আপনার ভিপিএন কনফিগারেশনটি দেখুন some কিছু ক্ষেত্রে আপনি দেখতে পারেন সেখানেও নির্ধারিত আইপি ঠিকানা there এখন আমরা এই বাগ রিপোর্টটি বন্ধ করছি "" :(

---- আপডেট 2016/11/04 ----

আমি আবার সমস্যায় পড়েছি এবং এটি সমাধানের জন্য আমাকে @ ডেভিডএইচ এর উত্তর আরও সংশোধন করতে হবে:

আমি 4 জি নেটওয়ার্কে ছিলাম এবং আমি এই ঠিকানাটি পেয়েছি:

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";
}

তার আসল উত্তরের সাথে আমি ওয়াইফাই আইপি fe80 পেয়ে যাব: 8 ডিডি: 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;
     }
 } ];

ভিপিএন সমস্যা সম্পর্কে আমি অভ্যন্তরীণ ফোরামে পোস্ট করেছি, অ্যাপল ইঞ্জিনিয়ার সাহায্যের প্রস্তাব দিয়েছেন। আমি আপনাকে আমার সাথে ম্যাক ডট কম
এইচ

1

এই ফাইলটিতে দ্রুত পরিবর্তন করার জন্য দুর্দান্ত সমাধান যা সমস্ত বিবরণ সরবরাহ করে।

আমার একটি অ্যাপে আমার ওয়াইফাই আইপি ঠিকানা আনতে হবে। আমি উপরের উত্তরগুলি ব্যবহার করেছি, তিনটি দ্রুতগতিতে:

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
   }
}

এই কোডে, এটি ক্র্যাশ হয়েছে কারণ আমি nilstatementচ্ছিক হিসাবে ব্যবহার করেছি প্রতিটি বিবৃতিতে আমাকে পরীক্ষা করতে হবে ?। সুতরাং আমার ক্লাসে প্রদত্ত লিঙ্কযুক্ত ফাইলটি ব্যবহার করা আমার পক্ষে ভাল। আমার মতো এখন চেক করা সহজ হয়ে যায়:

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" এর মতো ঠিকানা হিসাবে দুটি ইন্টারফেস দেয়


1
একটি সম্ভাব্য সমাধানের একটি লিঙ্ক সর্বদা স্বাগত, তবে দয়া করে লিঙ্কটির চারপাশে প্রসঙ্গটি যুক্ত করুন যাতে আপনার সহ ব্যবহারকারীদের এটি কী এবং কেন আছে তা কিছুটা ধারণা থাকতে পারে। টার্গেট সাইটটি যদি অ্যাক্সেসযোগ্য না হয় বা স্থায়ীভাবে অফলাইনে চলে যায় তবে সর্বদা গুরুত্বপূর্ণ লিঙ্কের সর্বাধিক প্রাসঙ্গিক অংশটি উদ্ধৃত করুন। বিবেচনায় রাখুন যে কোনও বাহ্যিক সাইটের লিঙ্কের চেয়ে সবেমাত্র বেশি হওয়া একটি সম্ভাব্য কারণ কেন এবং কীভাবে কিছু উত্তর মুছে ফেলা হয়?
পল রাউব

1
আরও ভাল বোঝার জন্য এটি আমার পক্ষে কতটা সহায়ক হিসাবে ঠিক সেই অনুযায়ী আপডেট হবে
সর্বাধিক

1

আইপি ঠিকানা পাওয়ার জন্য আমি একটি সহজ ফাইল তৈরি করেছি। আমি এই সমাধানটি @ লুন্ডজেম, @ ডেভিডএইচ এবং @ ইহুনাথের উত্তরগুলির ভিত্তিতে তৈরি করেছি। এটি তারযুক্ত সংযোগ বিবেচনা করে। যদিও আমি এই সমাধানে ভিপিএন অন্তর্ভুক্ত করি নি।

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

আইওএসে 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;
}
আমাদের সাইট ব্যবহার করে, আপনি স্বীকার করেছেন যে আপনি আমাদের কুকি নীতি এবং গোপনীয়তা নীতিটি পড়েছেন এবং বুঝতে পেরেছেন ।
Licensed under cc by-sa 3.0 with attribution required.