Доступ к IP-адресу с NSHost - PullRequest
5 голосов
/ 16 июля 2010

Я пытаюсь получить IP-адрес, используя NSHost. С объектом NSHost я могу использовать метод адреса для доступа к массиву объектов, одним из которых является IP-адрес. Я боюсь, что IP-адрес может изменить положение в массиве с одной машины на другую. Есть ли способ получить доступ к этой информации универсальным способом?

Была попытка ответить на этот вопрос в предыдущем посте, но, как вы можете видеть, он терпит неудачу.

IP-адрес? - какао

Вот мой код:

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

Ответы [ 7 ]

11 голосов
/ 21 июля 2010

Единственное, о чем я могу думать, - это использовать что-то вроде "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;}
9 голосов
/ 17 июля 2010

Я использовал это на многих машинах без проблем.

 -(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;объявляется еще где

1 голос
/ 22 сентября 2015

Сделан служебный класс для поиска 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
1 голос
/ 04 апреля 2014

Я хотел обновить свой оригинальный ответ при получении внешнего ip.

Не так много изменений, но я хотел показать, как получить и проанализировать HTML с использованием NSXMLDocument и Xquary

Это также дает небольшую иллюстрацию того, как вы можете анализировать 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]);
    }
}
0 голосов
/ 05 февраля 2013

Вы можете создать категорию на 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

Это работает очень быстро и хорошо. Если вам нужна другая информация или для мониторинга, используйте каркас конфигурации системы.

0 голосов
/ 19 июля 2010

Мой первый ответ - указать частный IP-адрес, назначенный устройству в частной сети, например, с вашего маршрутизатора.

Если вы хотите увидеть общедоступный IP-адрес, то есть тот, который подключен к Интернету. Обычно назначается вашим поставщиком услуг. Вы можете посмотреть на ответ Джим Дави -> здесь

Я проверил это, и оно работало хорошо, но прочитайте остальные комментарии и ответы, которые указывают на неясности в попытке получить публичный IP.

0 голосов
/ 16 июля 2010

Как ответили на вопрос, который вы упомянули выше, существует множество IP-адресов, которые может иметь одна машина. Если это то, что вы хотите, то вам лучше использовать метод NSHost names для получения массива имен, который вы можете затем отфильтровать по суффиксу (то есть * .lan), чтобы получить имя хоста, который вы хочу с этим именем. В моем случае. .lan адрес возвращает мой сетевой IP-адрес в виде точечного квадрата.

Если вы хотите найти внешний IP-адрес, то это хороший ответ , чтобы посмотреть.

...