Как подключить python-сокеты в многопоточном приложении - PullRequest
0 голосов
/ 09 апреля 2019

Я хочу написать простой сканер портов.Сделайте это следующим образом:

class Scanner(object):
    def __init__(self, addr=None):
        self._addr = addr if addr else '127.0.0.1'
        self._lock = Lock()
        self._opened_ports = []

    def __enter__(self):
        return self

    def __exit__(self, exc_type, exc_val, exc_tb):
        return True if not exc_val else False

    def _scan_ports(self, thread_num):    
        from_port = 1000 * thread_num
        ports_count = 1000

        for port in range(ports_count):
            try:
                sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
                sock.connect((self._addr, from_port + port))
                with self._lock:
                    self._opened_ports.append(from_port + port)
            except:
                pass
            finally:
                sock.close()

    def scan(self, num_threads=None):
        if not num_threads:
            num_threads = len(os.sched_getaffinity(0))
        pool = ThreadPool(num_threads)

        thread_numbers = [thread_num for thread_num in range(num_threads)]

        pool.map(self._scan_ports, thread_numbers)
        pool.close()
        pool.join()

        return sorted(self._opened_ports)

Как видно, я пытаюсь подключить сокеты к портам параллельно.Поэтому я запускаю его в многопоточном режиме следующим образом:

with Scanner() as scanner:
    ports = scanner.scan()

На моем ядре i7 с 8 ядрами это занимает около 200 мс.Если я делаю то же самое в 1 потоке, как это:

with Scanner() as scanner:
    ports = scanner.scan(1)

, это занимает 100 мс.

Я не понимаю, почему я получаю такой результат.Почему сканирование 1000 портов в 1 потоке требует в 2 раза меньше времени, чем сканирование 1000 портов в 8 потоках?Объясните мне, пожалуйста.

UPD если я заменим сокет на простой time.leep, он будет работать так, как я ожидаю - многопоточный режим занимает то же время, что и однопоточный, так что же плохого в сокетах?

1 Ответ

0 голосов
/ 10 апреля 2019

Кажется, это проблема localhost. Если я сканирую любой другой IP, а не localhost, он работает лучше.

...