2013-12-17 208 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