如何在多线程应用程序中连接python套接字

时间:2019-04-09 16:18:18

标签: python sockets threadpool python-multithreading

我想编写简单的端口扫描程序。如下所示:

PyDrive

可以看到,我正在尝试将套接字并行连接到端口。所以我在这样的多线程模式下运行它:

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)

在具有8个内核的i7内核上,它大约需要200毫秒。如果我在1个线程上做同样的事情:

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

占用100毫秒。

我不明白为什么我会得到这样的结果。为什么在1个线程中扫描1000个端口所需的时间比在8个线程中扫描1000个端口所需的时间少2倍?请告诉我。谢谢。

UPD 如果我用简单的time.sleep替换套接字的东西,它就会按我的预期工作-多线程模式与单线程模式占用的时间相同,那么套接字有什么不好呢?

1 个答案:

答案 0 :(得分:0)

似乎是本地主机问题。如果我扫描其他任何IP,而不是本地主机,则效果更好。