我正在尝试使用NSHost
获取IP地址。使用NSHost
对象,我可以使用addresses方法访问对象数组,其中一个对象是IP地址。我担心IP地址可能会改变阵列中从一台机器到另一台机器的位置。有没有办法以通用的方式访问这些信息?
有人试图在之前的帖子中回答这个问题,但你可以看到它不足。
这是我的代码:
+(NSString *) ipAddress {
NSHost * h = [[[NSHost currentHost] addresses] objectAtIndex:1];
return h ;
}
答案 0 :(得分:11)
我唯一能想到的就是使用“http://www.dyndns.org/cgi-bin/check_ip.cgi之类的东西”,其他人可能会有更好的方法。
这是一个例子,(即快速拼凑的代码)
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;}
答案 1 :(得分:9)
我在许多机器上使用过它而没有任何问题。
-(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;在其他地方宣布
答案 2 :(得分:1)
我想更新关于获取外部IP的原始答案。
没有太多变化,但我想展示如何使用NSXMLDocument和Xquary
来获取和解析HTML这也简要说明了如何通过获取节点来解析HTML。在我看来哪个更直接。尽管NSXMLDocument最初用于XML,但它将解析HTML DOM树
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]);
}
}
答案 3 :(得分:1)
制作实用程序类以查找IP地址。简约的方法。您可以使用更多条件或正则表达式检查来证明它。
NSLog(@"Addresses: %@", [[NSHost currentHost] addresses]);
这是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"
测试方法,
- (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
答案 4 :(得分:0)
正如您在上面提到的问题的答案所说,单个机器可以拥有多种IP地址。如果这是你想要的,那么你可能最好使用NSHost的names
方法来获取一个名称数组,然后你可以过滤后缀(即* .lan)以获取名称你想要这个名字的主人。就我而言。 .lan地址以虚线四边形的形式返回我的网络IP地址。
如果您想查找外部IP地址,请查看good answer。
答案 5 :(得分:0)
我的第一个答案是提供从专用网络分配给计算机的专用IP地址,例如路由器。
如果你想看到面向互联网的公共IP。通常由您的服务提供商分配。您可能希望通过 Jim Dovey - &gt;来查看答案。 here
我对它进行了测试并且运行良好,但请阅读其余的评论和答案,这些意见和答案指出了尝试获取公共IP的模糊性。
答案 6 :(得分:0)
您可以在NSHost上创建一个类别并执行以下操作:
#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
这非常快速而且很好。如果您需要其他信息或进行监控,请使用系统配置框架。