Сравнение IP-адресов iOS в диапазоне IP-адресов

Я разрабатываю приложение, которое показывает контент в зависимости от страны, поэтому я получаю IP-адрес пользователя, проблема в том, как проверить, находится ли этот IP-адрес между двумя IP-адресами. Пример:

если у меня этот IP: myIP = 127.0.0.1

как я могу проверить, находится ли он в этом диапазоне: IP1 = 2.88.0.0; IP2 = 2,91,255,255;

Спасибо.


person M.Alatrash    schedule 09.02.2014    source источник


Ответы (2)


127.0.0.1 - это адрес устройства обратной связи. Вам нужен адрес en0 или любой другой, который является устройством, подключенным к Wi-Fi / мобильной сети. (Можно перечислить все адреса устройств с помощью getifaddrs(); см. ТАК вопрос).

Для IPv4-адреса значение может быть представлено с помощью 32-битного unsigned int, поэтому изменение диапазона так же просто, как:

BOOL inRange = ipAddress >= rangeStart && ipAddress <= endRange;

См. Этот вопрос SO.

EDIT OP, похоже, застрял на преобразовании IP-адреса, представленного с использованием точечной нотации в строке (например, «2.88.0.0») и unsigned int, о котором я говорю. Для этого я отсылаю его к _ 6_, которая используется для выполнения этого преобразования. Вы получите множество посещений в Интернете, если будете искать эту функцию и способы ее использования.

ИЗМЕНИТЬ 2. Хорошо, я добавлю более полный ответ, поскольку у OP все еще есть проблемы:

Я думаю, что вам не хватает WRT при использовании inet_aton() ключевой информации, это порядок байтов. Существует концепция сетевого порядка байтов, которая является прямым порядком байтов, учитывая, что основатели Интернета использовали для разработки Dec PDP 11. Большинство компьютеров в наши дни работают с прямым порядком байтов. Таким образом, вам нужно добавить htonl() в смесь, которая является функцией для преобразования из сети в порядок байтов хоста (где l означает длинный, что на самом деле является 32-битным).

So:

#import <Foundation/Foundation.h>
#import <sys/socket.h>
#import <netinet/in.h>
#import <arpa/inet.h>

@interface NetworkStuff : NSObject
- (uint32_t)convertIpAddress:(NSString *)ipAddress;
- (BOOL)ipAddress:(NSString *)ipAddress isBetweenIpAddress:(NSString *)rangeStart
     andIpAddress:(NSString *)rangeEnd;
@end

@implementation NetworkStuff
- (uint32_t)convertIpAddress:(NSString *)ipAddress {
    struct sockaddr_in sin;
    inet_aton([ipAddress UTF8String], &sin.sin_addr);
    return ntohl(sin.sin_addr.s_addr);
}

- (BOOL)ipAddress:(NSString *)ipAddress isBetweenIpAddress:(NSString *)rangeStart
     andIpAddress:(NSString *)rangeEnd {
    uint32_t ip = [self convertIpAddress:ipAddress];
    uint32_t start = [self convertIpAddress:rangeStart];
    uint32_t end = [self convertIpAddress:rangeEnd];
    return ip >= start && ip <= end;
}

@end

#define BOOLSTR(b) (b ? @"YES" : @"NO")

int main()
{  
    @autoreleasepool{
        NetworkStuff *networkStuff = [NetworkStuff new];
        NSLog(@"%@", BOOLSTR([networkStuff ipAddress:@"2.90.1.2" isBetweenIpAddress:@"2.88.0.0" andIpAddress:@"2.91.255.255"]));
        NSLog(@"%@", BOOLSTR([networkStuff ipAddress:@"2.92.1.2" isBetweenIpAddress:@"2.88.0.0" andIpAddress:@"2.91.255.255"]));
    }
    return 0;
}

$ clang -DDEBUG=1 -g -fobjc-arc -o iprange iprange.m -framework Foundation
$ ./iprange
2014-02-10 09:42:29.530 iprange[14693:707] YES
2014-02-10 09:42:29.532 iprange[14693:707] NO
person trojanfoe    schedule 09.02.2014
comment
спасибо за ваш ответ, но если я сделаю это NSRange range = NSMakeRange (2.88.0.0, 2.91.255.255); это дает мне предупреждение, что 2.88.0.0 не является int или double .. и т. д. - person M.Alatrash; 09.02.2014
comment
Также могут быть другие вещи, которые следует учитывать: адрес Wi-Fi может быть локальным адресом, если вы находитесь за маршрутизатором с NAT. Мобильный адрес может быть адресом IPv6 ... - person Martin R; 09.02.2014
comment
@MKAlatrash: Я не вижу никакой связи между ответом Trojanfoe и NSMakeRange (). - person Martin R; 09.02.2014
comment
@MartinR точно, его ответ - о достижимости: o - person M.Alatrash; 09.02.2014
comment
@MKAlatrash: Я имел в виду именно это! Trojanfoe показал вам, как именно проверить, находится ли IPv4-адрес в заданном диапазоне. Так почему вы пытаетесь использовать NSMakeRange ()? - person Martin R; 09.02.2014
comment
@MKAlatrash Я обновил свой ответ функцией, которую вам нужно преобразовать между точечной нотацией и unsigned int. - person trojanfoe; 09.02.2014
comment
@trojanfoe Большое спасибо, я над этим работаю. Сообщу, если сработает :) - person M.Alatrash; 09.02.2014
comment
@trojanfoe функция inet_aton () помогла, спасибо :), но я использовал другой способ сделать это. увидеть ответ - person M.Alatrash; 10.02.2014

Сначала я преобразовал IP-адрес в число, используя следующий метод:

-(double)getIpAsNumberr:(NSString *)ip
{
    NSArray *ipParts = [ip componentsSeparatedByString:@"."];
    double result = 0;

    for (int i = 0; i < 4; i++)
    {
        result += [ipParts[i]doubleValue] * (pow(256, (3 - i)));
    }

    return result;
}

После преобразования IP-адресов я использую следующий метод, чтобы определить, попадает ли IP-адрес в некоторый диапазон, например между 2.88.0.0 и 2.91.255.255:

-(BOOL)isBetween:(NSString *)myIPAddress fromRange:(NSString *)from ToRange:(NSString *)to
{
    double myIpAsNumber = [self getIpAsNumberr:myIPAddress];
    double ipFromAsNumber = [self getIpAsNumberr:from];
    double ipToAsNumber = [self getIpAsNumberr:to];

    BOOL inRange = myIpAsNumber >= ipFromAsNumber && myIpAsNumber <= ipToAsNumber;

    return inRange;
}

Вот и все.

Следующий метод, который я использовал для преобразования IP-адреса в целое число без знака (у меня не сработал, поэтому я использовал приведенный выше):

-(double)getIpAsUnSignedInteger:(NSString *)ip
{
    struct sockaddr_in antelope;
    char *some_addr;
    const char *ipUnsigned = [ip cStringUsingEncoding:NSStringEncodingConversionAllowLossy];

    inet_aton(ipUnsigned, &antelope.sin_addr); // store IP in antelope

    some_addr = inet_ntoa(antelope.sin_addr); // return the IP
    printf("%s\n", some_addr); // prints the IP Address

    // and this call is the same as the inet_aton() call, above:
    antelope.sin_addr.s_addr = inet_addr(ipUnsigned);

    NSString *ipAsNumber = [NSString stringWithFormat:@"%u",antelope.sin_addr.s_addr];
    NSLog(@"ssss == %@",ipAsNumber);

    return [ipAsNumber doubleValue];
}
person M.Alatrash    schedule 10.02.2014
comment
Почему double? Адрес IPv4 может быть представлен с помощью 32-битного целого числа без знака. - person trojanfoe; 10.02.2014
comment
Я попытался сделать его 32-битным целым числом, и оно изменилось ... но когда я попытался сравнить, это не сработало ... Я опубликую метод, который я использовал для преобразования его в 32-битное целое число. - person M.Alatrash; 10.02.2014
comment
@trojanfoe см. Edit, в котором я добавил метод преобразования IP-адреса в UnSigned Integer. - person M.Alatrash; 10.02.2014
comment
Хорошо, я добавил более полный ответ, так как вы, кажется, теряетесь, ни к чему не придете. - person trojanfoe; 10.02.2014
comment
О, спасибо, чувак @trojanfoe, за твой ответ. Я пойду с твоим решением, оно лучше моего - person M.Alatrash; 10.02.2014