iOS / Objective-C中的TCP客户端 - 检查开放端口

时间:2014-02-16 04:11:09

标签: ios iphone objective-c tcp cocoaasyncsocket

0我已经在关于AsyncSocket的几个问题上进行了挖掘,但没有点击任何内容。我觉得我想要做的事情相当简单,所以它会面对面......我已经尝试过非GCD版本,但也没有喜悦。

我需要能够针对特定的开放TCP端口扫描一系列主机。不幸的是,我没有控制服务器代码让它使用Bonjour宣布自己。所以,我是蛮力扫描,只是尝试连接那个端口 - 如果我得到'拒绝连接',那么我知道继续前进......

这一切都让我想到了AsyncSocket,我认为它是适合这项工作的工具。使用作者的例子,我有一个基本的工作示例,但并不完全。就像他的样本一样,我只是为了简单而使用主队列。问题是,对于委托方法是否被调用似乎是一个废话。有时socketDidDisconnect:触发,有时不触发。在这种特殊情况下,我知道端口5002在192.168.1.7上打开。但是,当它到达数组中的那个元素时,didConnectToHost不会触发。但是,如果我从IP列表中删除除.7之外的所有内容,则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 个答案:

答案 0 :(得分:1)

我尝试了类似的东西,我首先找到了自己的IP,然后修改它以显示整个子网范围。我得到的东西像&#34; 192.168.10。&#34;然后我做了

- (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,它也不会触发委托方法。

总结我的经验:循环似乎以某种方式阻止了委托方法。我怀疑它只是意味着连接到一个地址?那么它将是用于扫描子网的错误工具。

修改 我找到了一个很好的解决方为了扫描整个网络,我开始使用以下代码:

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

诀窍是等待套接字超时,然后启动新连接。这样,您就可以在可容忍的时间间隔内扫描整个网络。

希望这可以帮助你或其他人。