Differences

This shows you the differences between two versions of the page.

Link to this comparison view

c_11:examples:port_scanner.cc [2017/02/25 18:04] (current)
mike created
Line 1: Line 1:
 +====== Port Scanner ======
 +
 +<file c++ port_scanner.cc>​
 +#include <​cstdlib>​
 +#include <​iomanip>​
 +#include <​iostream>​
 +#include <​SFML/​Network.hpp>​
 +#include <​sstream>​
 +#include <​string>​
 +#include <​vector>​
 +
 +static bool port_is_open(const std::​string&​ address, int port)
 +{
 +    return (sf::​SocketTCP().connect(address,​ port) == sf::​Socket::​Done);​
 +}
 +
 +static std::​vector<​std::​string>​ split(const std::​string&​ string,
 +                                      char delimiter = ' ',
 +                                      bool allow_empty = false)
 +{
 +    std::​vector<​std::​string>​ tokens;
 +    std::​stringstream sstream(string);​
 +    std::string token;
 +    while (std::​getline(sstream,​ token, delimiter)) {
 +        if (allow_empty || token.size() > 0)
 +            tokens.push_back(token);​
 +    }
 +    return tokens;
 +}
 +
 +static int string_to_int(const std::​string&​ string)
 +{
 +    std::​stringstream sstream(string);​
 +    int i;
 +    sstream >> i;
 +    return i;
 +}
 +
 +template <​typename T>
 +static void swap(T& a, T& b)
 +{
 +    T c = a;
 +    a = b;
 +    b = c;
 +}
 +
 +template <​typename T>
 +static std::​vector<​T>​ range(T min, T max)
 +{
 +    if (min > max)
 +        swap(min, max);
 +    if (min == max)
 +        return std::​vector<​T>​(1,​ min);
 +    std::​vector<​T>​ values;
 +    for (; min <= max; ++min)
 +        values.push_back(min);​
 +    return values;
 +}
 +
 +static std::​vector<​int>​ parse_ports_list(const std::​string&​ list)
 +{
 +    std::​vector<​int>​ ports;
 +    for (const std::​string&​ token : split(list, ','​)) {
 +        std::​vector<​std::​string>​ strrange = split(token,​ '​-'​);​
 +        switch (strrange.size()) {
 +            case 0: ports.push_back(string_to_int(token)); ​      ​break;​
 +            case 1: ports.push_back(string_to_int(strrange[0]));​ break;
 +            case 2:
 +            {
 +                int min = string_to_int(strrange[0]),​
 +                    max = string_to_int(strrange[1]);​
 +                for (int port : range(min, max))
 +                    ports.push_back(port);​
 +                break;
 +            }
 +            default:
 +                break;
 +        }
 +    }
 +    return ports;
 +}
 +
 +template <​typename T>
 +static T maximum(const std::​vector<​T>&​ values)
 +{
 +    T max = values[0];
 +    for (T value : values) {
 +        if (value > max)
 +            max = value;
 +    }
 +    return max;
 +}
 +
 +template <​typename T>
 +static size_t digits(T value)
 +{
 +    size_t count = (value < 0) ? 1 : 0;
 +    if (value == 0)
 +        return 0;
 +    while (value) {
 +        value /= 10;
 +        ++count;
 +    };
 +    return count;
 +}
 +
 +int main(int argc, char* argv[])
 +{
 +    std::string address;
 +    std::​vector<​int>​ ports;
 +    if (argc == 3) {
 +        address = argv[1];
 +        ports = parse_ports_list(std::​string(argv[2]));​
 +    } else {
 +        std::string port_list;
 +        std::cout << "​Address:​ " << std::flush;
 +        std::​getline(std::​cin,​ address);
 +        std::cout << "Port: " << std::flush;
 +        std::​getline(std::​cin,​ port_list);
 +        ports = parse_ports_list(port_list);​
 +    }
 +    std::cout << "​Showing open ports on " << address << "​...\n";​
 +    size_t width = digits(maximum(ports));​
 +    for (int port : ports) {
 +        if (port_is_open(address,​ port))
 +            std::cout << "Port " << std::​setw(width) << port << " : OPEN\n";​
 +    }
 +    std::cout << std::flush;
 +    return 0;
 +}
 +</​file>​