Я пишу сканер портов на Python, и основной код выглядит следующим образом:
import socket
import sys
import threading
def scan_port(host, port, timeout):
addr = str(host), int(port)
conn = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
conn.settimeout(float(timeout))
try:
conn.connect(addr)
print(f'- {port} open')
except Exception as error:
print(f'- {port} closed: {error!r}')
finally:
conn.close()
if __name__ == '__main__':
host = sys.argv[1]
pmin = int(sys.argv[2])
pmax = int(sys.argv[3])
threads = []
for port in range(pmin, pmax+1):
args = [host, port, 1.0]
thread = threading.Thread(target=scan_port, args=args)
thread.start()
threads.append(thread)
for thread in threads:
thread.join()
Когда я запускаю этот скрипт на одном порту, он всегда подключается:
$ python scantest.py google.com 80 80
- 80 open
Но когда я запускаю его на большой последовательности портов (не менее 100), он всегда завершается ошибкой (с общей ошибкой «тайм-аута»):
$ python scantest.py google.com 1 100
- 1 closed: timeout('timed out')
- 2 closed: timeout('timed out')
- 3 closed: timeout('timed out')
- 4 closed: timeout('timed out')
# etc...
Есть ли какая-то особенность Python, которая мешаетмне от многопоточности большое количество сокетных соединений, или я пропускаю некоторые основные препятствия?Я запускаю это на Windows 8, если это поможет.Спасибо.
Редактировать: Судя по дальнейшим исследованиям, кажется, что существует ограничение на количество соединений сокетов, которые система может пытаться выполнить одновременно.Я заново реализовал этот скрипт с ThreadPoolExecutor
из модуля concurrent.futures
, и он значительно повысил надежность (за счет скорости).