Differences
This shows you the differences between two versions of the page.
| — |
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> | ||