Accessing IP Address with NSHost
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
Eric Brotto
Updated on June 19, 2022Comments
-
Eric Brotto almost 2 years
I am trying to get the IP Address using
NSHost
. With theNSHost
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.
Here is my code:
+(NSString *) ipAddress { NSHost * h = [[[NSHost currentHost] addresses] objectAtIndex:1]; return h ; }