使用 NSHost 访问 IP 地址

发布于 2024-09-10 01:38:50 字数 433 浏览 5 评论 0原文

我正在尝试使用 NSHost 获取 IP 地址。通过 NSHost 对象,我可以使用地址方法来访问对象数组,其中之一是 IP 地址。但我担心 IP 地址可能会改变阵列中从一台机器到另一台机器的位置。有没有一种方法可以通用地访问这些信息?

在上一篇文章中曾尝试回答这个问题,但正如您所看到的,它没有达到要求。

IP 地址? - 可可

这是我的代码:

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

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

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(7

荆棘i 2024-09-17 01:38:50

我唯一能想到的就是使用类似“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;}

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;}
葬﹪忆之殇 2024-09-17 01:38:50

我在很多机器上使用过这个,没有任何问题。

 -(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 *字符串地址;在其他地方声明

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

机场等船 2024-09-17 01:38:50

我想更新关于获取外部 IP 的原始答案。

没有太多变化,但我想展示如何使用 NSXMLDocumentXquary

这也提供了如何通过获取节点来解析 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]);
    }
}

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]);
    }
}
久而酒知 2024-09-17 01:38:50

创建了一个实用程序类来查找 IP 地址。简约的方法。您可以通过更多条件或正则表达式检查来增强它。

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

返回的列表

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

这是 NSHost测试方法

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

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
顾冷 2024-09-17 01:38:50

正如您上面提到的问题的答案所说,一台机器可以拥有多种IP地址。如果这就是您想要的,那么您最好使用 NSHost 的 names 方法来获取名称数组,然后您可以过滤后缀(即 *.lan)以获得名称数组您想要使用此名称的主机的名称。就我而言。 .lan 地址以点线四边形形式返回我的网络 IP 地址。

如果你想找到外部IP地址,那么这是一个 很好的答案看看。

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

If you want to find the external ip address, then this is a good answer to look at.

眼眸 2024-09-17 01:38:50

我的第一个答案是提供从您的路由器分配给专用网络上的机器的专用 IP 地址。

如果你想查看公网IP,那就是面向互联网的IP。通常由您的服务提供商分配。您可能想看看 Jim Dovey 的答案 --> 这里

我测试了它,效果很好,但请阅读其余的评论和答案,这些评论和答案指出了试图获得公共 IP 时的含糊之处。

My first Answer is to supply the Private IP address assigned to the Machine on private network from say your router.

If you want to see the public IP, which is the one facing the internet. Normally assigned by your service provider. You may want to look at the answer by Jim Dovey --> here

I tested it and it worked well, but read the rest of the comments and answers which point to ambiguities in trying to get a public IP.

风透绣罗衣 2024-09-17 01:38:50

您可以在 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

这工作得非常快而且效果很好。如果您需要其他信息或进行监控,请使用系统配置框架。

You can create a category on 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

This works really fast and well. If you need other info or to monitor then use System Configuration framework.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文