Access IP Address with NSHost

I am trying to get an IP address using NSHost . With an NSHost object NSHost I can use the address method to access an array of objects, one of which is an IP address. I am afraid that the IP address may change the position in the array from one machine to another. 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, this is not consistent.

IP address? - Cocoa

Here is my code:

 +(NSString *) ipAddress { NSHost * h = [[[NSHost currentHost] addresses] objectAtIndex:1]; return h ; } 
+5
objective-c cocoa ip-address nshost
source share
7 answers

I used this on many machines without any 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; declared otherwise where

+9
source share

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 (e.g. fast forged 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;} 
+11
source share

I wanted to update my original response to getting an external ip.

Not many changes, but I wanted to show how to get and parse HTML using NSXMLDocument and Xquary

It also gives a small illustration of how you can parse HTML by getting nodes. Which, in my opinion, is more straightforward. Although NSXMLDocument is natively 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 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]); } } 
+1
source share

Created a utility class for finding IP addresses. Minimalist approach. You can expand it by using additional conditions or by checking regular expressions.

  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" 

Testing 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 
+1
source share

As already mentioned, the answers to the above question contain many IP addresses that a single machine can have. If this is what you want, then you might be better off using the NSHost names method to get an array of names, which you can then filter for a suffix (i.e. * .lan) to get the host name that you want with that name . In my case. the .lan address returns my network IP as a dotted square.

If you want to find an external IP address, then this is a good answer to take a look.

0
source share

My first answer is to provide the private IP address assigned to the computer on the private network from your router.

If you want to see the public IP address that is on the Internet. Usually assigned by your service provider. You can see Jim Dovey's answer → here

I tested it and it worked well, but read the rest of the comments and answers, which indicate ambiguities in an attempt to get a public IP address.

0
source share

You can create a category in NSHost and do something like this:

 #import <arpa/inet.h> #import <ifaddrs.h> #import <net/if.h> 

.h

 + (NSDictionary *) interfaceIP4Addresses; + (NSDictionary *) interfaceIP6Addresses; + (NSDictionary *) interfaceIPAddresses; 

.m

 typedef NS_ENUM(NSUInteger, AddressType) { AddressTypeBoth = 0, AddressTypeIPv4 = 1, AddressTypeIPv6 = 2 }; @implementation SomeClass #pragma mark - Helper Methods: + (NSDictionary *) _interfaceAddressesForFamily:(AddressType)family { NSMutableDictionary *interfaceInfo = [NSMutableDictionary dictionary]; struct ifaddrs *interfaces; if ( (0 == getifaddrs(&interfaces)) ) { struct ifaddrs *interface; for ( interface=interfaces; interface != NULL; interface=interface->ifa_next ) { if ( (interface->ifa_flags & IFF_UP) && !(interface->ifa_flags & IFF_LOOPBACK) ) { const struct sockaddr_in *addr = (const struct sockaddr_in *)interface->ifa_addr; if ( addr && addr->sin_family == PF_INET ) { if ( (family == AddressTypeBoth) || (family == AddressTypeIPv4) ) { char ip4Address[INET_ADDRSTRLEN]; inet_ntop( addr->sin_family, &(addr->sin_addr), ip4Address, INET_ADDRSTRLEN ); [interfaceInfo setObject:[NSString stringWithUTF8String:interface->ifa_name] forKey:[NSString stringWithUTF8String:ip4Address]]; } } else if ( addr && addr->sin_family == PF_INET6 ) { if ( (family == AddressTypeBoth) || (family == AddressTypeIPv6) ) { char ip6Address[INET6_ADDRSTRLEN]; inet_ntop( addr->sin_family, &(addr->sin_addr), ip6Address, INET6_ADDRSTRLEN ); [interfaceInfo setObject:[NSString stringWithUTF8String:interface->ifa_name] forKey:[NSString stringWithUTF8String:ip6Address]]; } } } } freeifaddrs( interfaces ); } return [NSDictionary dictionaryWithDictionary:interfaceInfo]; } #pragma mark - Class Methods: + (NSDictionary *) interfaceIP4Addresses { return [self _interfaceAddressesForFamily:AddressTypeIPv4]; } + (NSDictionary *) interfaceIP6Addresses { return [self _interfaceAddressesForFamily:AddressTypeIPv6]; } + (NSDictionary *) interfaceIPAddresses { return [self _interfaceAddressesForFamily:AddressTypeBoth]; } @end 

It works very fast and well. If you need other information or for monitoring, use the system configuration infrastructure.

0
source share

All Articles