2013-12-17 151 views
0

我想在C++中做一个端口扫描器,这样我就可以从我的网络中某些端口打开的某些设备获取IP地址。我实现了一个超时,因为当我测试网络中的每个IP地址时,如果我没有收到响应,它会自动关闭连接。C++端口扫描器

如果我把这个超时大约30秒的时间,它只是检测所有设备关闭,如果我把一个更大的值它挂起,永远不会结束。

#include <sys/socket.h> 
#include <sys/time.h> 
#include <sys/types.h> 
#include <arpa/inet.h> 
#include <netinet/in.h> 
#include <errno.h> 
#include <fcntl.h> 
#include <stdio.h> 
#include <netdb.h> 
#include <stdlib.h> 
#include <string.h> 
#include <unistd.h> 
#include <string> 

using namespace std;  

static bool port_is_open(string ip, int port){ 

    struct sockaddr_in address; /* the libc network address data structure */ 
    short int sock = -1;   /* file descriptor for the network socket */ 
    fd_set fdset; 
    struct timeval tv; 

    address.sin_family = AF_INET; 
    address.sin_addr.s_addr = inet_addr(ip.c_str()); /* assign the address */ 
    address.sin_port = htons(port); 

    /* translate int2port num */ 
    sock = socket(AF_INET, SOCK_STREAM, 0); 
    fcntl(sock, F_SETFL, O_NONBLOCK); 

    connect(sock, (struct sockaddr *)&address, sizeof(address)); 

    FD_ZERO(&fdset); 
    FD_SET(sock, &fdset); 
    tv.tv_sec = 0;    /* timeout */ 
    tv.tv_usec = 50; 

    if (select(sock + 1, NULL, &fdset, NULL, &tv) == 1) 
    { 
     int so_error; 
     socklen_t len = sizeof so_error; 

     getsockopt(sock, SOL_SOCKET, SO_ERROR, &so_error, &len); 

     if (so_error == 0){ 
      close(sock); 
      return true; 
     }else{ 
      close(sock); 
      return false; 
     } 
    }   
    return false; 
} 


int main(int argc, char **argv){  

    int i=1;   
    int port = 22;   
    while (i<255) {    
     string ip = "10.0.60.";       
     std::string host = std::to_string(i); 
     ip.append(host);    
     if (port_is_open(ip, port)){     
      printf("%s:%d is open\n", ip.c_str(), port);     
     }    
     i++; 
    }   
    return 0;   
} 
+1

30次使用? 30微秒超时? –

+2

你的问题是什么? –

+0

'tv.tv_usec = 50'等于50 usec – nrathaus

回答

2

你可以用你的逻辑到异步调用和并联一个合理的超时(如10秒内,因为30US在标准条件,而没有任何意义)开始。线程会加速你的程序周围255次,它会完成,在最坏的情况下,出现这种超时刚过:

... 
#include <iostream> 
#include <thread> 
#include <vector> 
#include <sstream> 
... 

void task(std::string ip, int port){ 
    if (port_is_open(ip, port)) 
     cout << ip << ":" << port << " is open\n"; 
} 

int main(int argc, char **argv){   
    const std::string ip_prefix = "10.0.60."; 
    const int port = 22; 
    std::vector<std::thread *> tasks; 

    for (int i=0; i<255; i++){  
     std::ostringstream ip; 
     ip << ip_prefix << i; 
     tasks.push_back(new std::thread(task, ip.str(), port)); 
    } 
    for (int i=0; i<255; i++){ 
     tasks[i]->join(); 
     delete tasks[i]; 
    } 
    return 0; 
} 

您可能要编译这样的:g++ -std=c++11g++ -std=c++0x -pthread(老年人GCC)。

+0

+1但是,难道你没有阅读所有关于只创建尽可能多的线程的多线程标签帖子,因为有核心? :)) –

+0

@Martin James:它被指定用于将来的机器;]但是,严重的是,我没有看到这些话题只关于创建与核心一样多的线程。多线程编程在过去也存在于单核处理器上,并且并不总是关于大量计算的硬件并行化,这会占用每个核心的大部分处理器能力。这也是关于提高效率,通过使用否则会被处理器浪费的时间,而它没有什么可做,而是等待例如内存,磁盘或网络操作来完成。 – jwaliszko

+0

@Martin James:(...)在这里,我们只是在每个线程中通过线路发送数据,并且我们不想因为等待响应而阻止每一步。我认为这样的逻辑很适合这里(参见[this](http://programmers.stackexchange.com/questions/97615/what-c​​an-multiple-threads-do-that-a-single-thread-cannot)),但我可能是错的。 – jwaliszko