Accessing IP Address with NSHost

14,844

Solution 1

I have used this on many machines without problems.

 -(void) getIPWithNSHost{
    NSArray *addresses = [[NSHost currentHost] addresses];

for (NSString *anAddress in addresses) {
    if (![anAddress hasPrefix:@"127"] && [[anAddress componentsSeparatedByString:@"."] count] == 4) {
         stringAddress = anAddress;
        break;
    } else {
        stringAddress = @"IPv4 address not available" ;
    }
}
        //NSLog (@"getIPWithNSHost: stringAddress = %@ ",stringAddress);    

}

NSString *stringAddress; is declared else where

Solution 2

The only thing I can think of is to use something like "http://www.dyndns.org/cgi-bin/check_ip.cgi" others may have a better way.

This is an example,(i.e a quick cobbled together code)

NSUInteger  an_Integer;
NSArray * ipItemsArray;
NSString *externalIP;

NSURL *iPURL = [NSURL URLWithString:@"http://www.dyndns.org/cgi-bin/check_ip.cgi"];

if (iPURL) {
    NSError *error = nil;
    NSString *theIpHtml = [NSString stringWithContentsOfURL:iPURL 
                                                  encoding:NSUTF8StringEncoding 
                                                     error:&error];
    if (!error) {
                NSScanner *theScanner;
        NSString *text = nil;

        theScanner = [NSScanner scannerWithString:theIpHtml];

        while ([theScanner isAtEnd] == NO) {

                // find start of tag
            [theScanner scanUpToString:@"<" intoString:NULL] ; 

                // find end of tag
            [theScanner scanUpToString:@">" intoString:&text] ;

                // replace the found tag with a space
                //(you can filter multi-spaces out later if you wish)
            theIpHtml = [theIpHtml stringByReplacingOccurrencesOfString:
                    [ NSString stringWithFormat:@"%@>", text]
                                                   withString:@" "] ;
            ipItemsArray =[theIpHtml  componentsSeparatedByString:@" "];
            an_Integer=[ipItemsArray indexOfObject:@"Address:"];

                externalIP =[ipItemsArray objectAtIndex:  ++an_Integer];



        } 


            NSLog(@"%@",externalIP);
    } else {
        NSLog(@"Oops... g %d, %@", 
              [error code], 
              [error localizedDescription]);
    }
}




[pool drain];
return 0;}

Solution 3

I wanted to update my original answer on getting an external ip.

There is not much change but I wanted to show how to get and parse the HTML with use NSXMLDocument and Xquary

This also gives a small illustration of how you can parse HTML by getting the nodes. Which in my opinion is more straight forward. Although NSXMLDocument is initially for XML it will parse the HTML DOM tree

    NSString *externalIP;

    ///--DYNDNS.ORG  URL

    NSURL *iPURL = [NSURL URLWithString:@"http://www.dyndns.org/cgi-bin/check_ip.cgi"];
    if (iPURL) {

        NSError *err_p = nil;


        //--use NSXMLDocument to get the url:(*Requests NSXMLNode to preserve whitespace characters (such as tabs and carriage returns) in the XML source that are not part of node content*)
    NSXMLDocument * xmlDoc = [[NSXMLDocument alloc] initWithContentsOfURL:iPURL
                                                                  options:(NSXMLNodePreserveWhitespace|
                                                                           NSXMLNodePreserveCDATA)
                                                                    error:&err_p];

    if (xmlDoc == nil) {

        //-- That did not work so lets see if we can change the malformed XML into valid XML during processing of the document.
        xmlDoc = [[NSXMLDocument alloc] initWithContentsOfURL:iPURL
                                                      options:NSXMLDocumentTidyXML
                                                        error:&err_p];

    }


    if (!err_p) {
 NSError * error;
        //-- We will use XQuary to get the text from the child node. Dyndns.org page is very simple. So we just need to get the Body text.

    NSString *xpathQueryTR =  @"//body/text()";
        //-- we get the first node's string value. We use string value to in effect cast to NSString.
        //We the seperate the string into components using a space. and obtain the last object in the returned array.
        //--This gives us the IP string without the "Current IP Address:" string.
    externalIP = [[[[[xmlDoc nodesForXPath:xpathQueryTR error:&error]objectAtIndex:0] stringValue]componentsSeparatedByString:@" "]lastObject];

    if (!error) {

    NSLog(@"%@",externalIP);

    }else {
        NSLog(@"Oops... g %ld, %@",
              (long)[error code],
              [error localizedDescription]);
    }

    }else {
        NSLog(@"Oops... g %ld, %@",
              (long)[err_p code],
              [err_p localizedDescription]);
    }
}

Solution 4

Made an utility class to find the IP addresses. Minimalistic approach. You can robustify it with more conditions or regex checking.

 NSLog(@"Addresses: %@", [[NSHost currentHost] addresses]);

This is the list returned by NSHost

 "fe80::1610:9fff:fee1:8c2f%en0",
 "192.168.212.61",
 "fe80::2829:3bff:fee6:9133%awdl0",
 "fe80::e54b:8494:bbc8:3989%utun0",
 "fd68:cc16:fad8:ded9:e54b:8494:bbc8:3989",
 "10.11.51.61",
 "::1",
 "127.0.0.1",
 "fe80::1%lo0"

Test method,

- (void)testHost {
    NSLog(@"Addresses: %@", [[NSHost currentHost] addresses]);

    for (NSString *s in [[NSHost currentHost] addresses]) {
        IPAddress *addr = [[IPAddress alloc] initWithString:s];
        if (![addr isLocalHost] && [addr isIPV4]) {
            // do something
        }
    }
}

IPAddress.h

#import <Foundation/Foundation.h>

@interface IPAddress : NSObject

@property (nonatomic, strong) NSString *IPAddress;

- (id)initWithString:(NSString *)ipaddress;

- (BOOL)isLocalHost;
- (BOOL) isIPV4;
- (BOOL) isIPV6;

@end

IPAddress.m

#import "IPAddress.h"

@implementation IPAddress

- (id)initWithString:(NSString *)ipaddress {
    self = [super init];
    if (self) {
        self.IPAddress = ipaddress;
    }
    return self;
}

- (BOOL)isLocalHost {
    if (self.IPAddress == nil) return NO;
    if ([@"127.0.0.1" compare:self.IPAddress options:NSCaseInsensitiveSearch] == NSOrderedSame) {
        return YES;
    }

    if ([@"localhost" compare:self.IPAddress options:NSCaseInsensitiveSearch] == NSOrderedSame) {
        return YES;
    }

    if ([@"::1" compare:self.IPAddress options:NSCaseInsensitiveSearch] == NSOrderedSame) {
        return YES;
    }

    return NO;
}

- (BOOL) isIPV4 {
    NSArray *ar = [self.IPAddress componentsSeparatedByString:@"."];
    if (ar.count == 4) {
        return YES;
    }
    return NO;
}

- (BOOL) isIPV6 {
    if (![self isIPV4]) {
        if ([self.IPAddress rangeOfString:@":"].location != NSNotFound) {
            return YES;
        }
    }
    return NO;
}

@end
Share:
14,844
Eric Brotto
Author by

Eric Brotto

Updated on June 19, 2022

Comments

  • Eric Brotto
    Eric Brotto almost 2 years

    I am trying to get the IP Address using NSHost. With the NSHost object I can use the addresses method to access an array of objects one of which is the IP Address. I fear though that the IP Address may change position in the array from one machine to the other. Is there a way to access this information in a universal way?

    There was an attempt to answer this question in a previous post, but as you can see it falls short.

    IP Address? - Cocoa

    Here is my code:

    +(NSString *) ipAddress {
        NSHost * h = [[[NSHost currentHost] addresses] objectAtIndex:1];
        return h ;  
    }