2014-02-16 2 views
1

0 Я выкопал несколько вопросов о SO о AsyncSocket, но ничего не нажал. Я чувствую, что то, что я пытаюсь сделать, довольно просто, так что это будет ладонь ... Я пробовал версию, отличную от GCD, но и радости там не было.TCP-клиент в iOS/Objective-C - проверка для открытого порта

Мне нужно иметь возможность сканировать ряд хостов для определенного открытого TCP-порта. К сожалению, у меня нет контроля над кодом сервера, чтобы он объявил себя с помощью Bonjour. Итак, я дошел до сканирования грубой силы и просто попытался подключиться к этому порту - если я получу «Соединение отказал», то я знаю, чтобы двигаться дальше ...

Все это привело меня к AsyncSocket, который Я считаю, что это правильный инструмент для работы. Используя примеры автора, у меня есть базовый рабочий пример, но не совсем. Как и его образцы, я просто использую основную очередь для простоты. Дело в том, что кажется, что это дерьмовая стрельба относительно того, вызван ли метод делегата. Иногда socketDidDisconnect: срабатывает, иногда нет. В этом конкретном случае я знаю, что порт 5002 открыт на 192.168.1.7. Однако, когда он попадает в этот элемент массива, didConnectToHost не срабатывает. Однако, если я удалю все, кроме .7 из списка IP-адресов, то didConnectToHost срабатывает. Я подозрительно, что вызов connectToHost: в таком замкнутом цикле проблема, но я не могу это доказать. Любая помощь будет оценена по достоинству. Если кто-то знает более простой способ сделать это, я открыт для этого. Удивительно, но на эту тему не так много. Заранее спасибо за вашу помощь!

Роб

#import "GCDAsyncSocket.h" 

#define PORT 5002 

@implementation ViewController 
{ 
    GCDAsyncSocket *asyncSocket; 
    NSMutableArray *availableHosts; 
} 

- (IBAction)startScan 
{ 
    NSArray *ipAddressList = @[@"192.168.1.1",@"192.168.1.2",@"192.168.1.3",@"192.168.1.4",@"192.168.1.5",@"192.168.1.6",@"192.168.1.7"]; 

    dispatch_queue_t mainQueue = dispatch_get_main_queue(); 

    asyncSocket = [[GCDAsyncSocket alloc] initWithDelegate:self delegateQueue:mainQueue]; 
    NSError *error = nil; 

    for (int i = 1; i < ipAddressList.count; i++) { 
     NSString *scanHostIP = ipAddressList[i]; 
     [asyncSocket connectToHost:scanHostIP onPort:PORT withTimeout:1 error:&error]; 
    } 
} 

- (void)socket:(GCDAsyncSocket *)sock didConnectToHost:(NSString *)host port:(UInt16)port 
{ 
    NSLog(@"Found open port %d on %@", port, host); 
    [availableBeds addObject:host]; 
    [sock setDelegate:nil]; 
    [sock disconnect]; 
    [sock setDelegate:self]; 

} 

- (void)socketDidDisconnect:(GCDAsyncSocket *)sock withError:(NSError *)err 
{ 
    NSLog(@"Disconnected: %@", err ? err : @""); 
} 

ответ

1

Я пытался что-то подобное, где я первый нашел свой собственный IP-адрес, а затем модифицированную его, чтобы отобразить диапазон всей подсети. Я получил что-то вроде «192.168.10». И затем я делаю

- (void)startScan:(NSString *)ipRange 
{ 
    dispatch_queue_t mainQueue = dispatch_get_main_queue(); 

    asyncSocket = [[GCDAsyncSocket alloc] initWithDelegate:self delegateQueue:mainQueue]; 
    NSError *error = nil; 

    for (int i = 1; i < 255; i++) { 
     NSString *scanHostIP = [NSString stringWithFormat:@"%@%d", ipRange, i]; 
     [asyncSocket connectToHost:scanHostIP onPort:PORT error:&error]; 
    } 
    //connect to an IP that listens on the certain port 
    [asyncSocket connectToHost:@"192.168.10.162" onPort:PORT error:&error]; 
} 

Когда я пытаюсь подключиться к 162 в цикле, метод делегата никогда не вызывается. Но когда я подключаюсь только к определенному IP-адресу, он неожиданно вызывает вызов. Интересно, что метод делегата не вызывается, когда я сначала запускаю цикл, а затем пытаюсь подключиться к конкретному хосту.

Я пытался подключиться и без тайм-аута, но и не трюк.

Я проверил метод connectToHost и он всегда что-то возвращает. Даже если я пытаюсь подключиться к 2 IP-адресам, он не запускает метод делегата.

Подводя итог моему опыту: цикл как бы блокирует метод делегата. Я подозреваю, что он предназначен только для подключения к одному адресу? Тогда это будет неправильный инструмент для сканирования подсети.

EDIT: Я нашел хорошее решение. Для сканирования всей сети я начал использоваться следующий код:

-(void)startScan 
{ 
    dispatch_queue_t mainQueue = dispatch_get_main_queue(); 

    asyncSocket = [[GCDAsyncSocket alloc] initWithDelegate:self delegateQueue:mainQueue]; 
    NSError *error = nil; 

    NSString *scanHostIP = [NSString stringWithFormat:@"%@%d", ipRange, count]; 
    [asyncSocket connectToHost:scanHostIP onPort:PORT withTimeout:0.01 error:&error]; 
} 

- (void)socketDidDisconnect:(GCDAsyncSocket *)sock withError:(NSError *)err 
{ 
    NSError *error; 
    if(count < 254) 
    { 
     count++; 
     NSString *scanHostIP = [NSString stringWithFormat:@"%@%d", ipRange, count]; 
     [asyncSocket connectToHost:scanHostIP onPort:PORT withTimeout:0.01 error:&error]; 
    } 
} 

Хитрость в том, чтобы ждать, пока сокет тайм-аут, а затем начать новое соединение. Таким образом, вы можете сканировать всю сеть в допустимый временной интервал.

Надеюсь, это поможет вам или кому-то еще.

Смежные вопросы