Warning: file_get_contents(/data/phpspider/zhask/data//catemap/3/sockets/2.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
如何在多线程应用程序中连接python套接字_Python_Sockets_Threadpool_Python Multithreading - Fatal编程技术网

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

如何在多线程应用程序中连接python套接字,python,sockets,threadpool,python-multithreading,Python,Sockets,Threadpool,Python Multithreading,我想写一个简单的端口扫描器。按如下方式操作: 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 __e

我想写一个简单的端口扫描器。按如下方式操作:

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()
with Scanner() as scanner:
    ports = scanner.scan(1)
在具有8个内核的core i7上,它大约占用200毫秒。如果我在1个线程上执行相同操作,如下所示:

with Scanner() as scanner:
    ports = scanner.scan()
with Scanner() as scanner:
    ports = scanner.scan(1)
它占用100毫秒

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


UPD如果我用simple time.sleep替换socket,它会像我期望的那样工作-多线程模式占用与单线程相同的时间,那么socket有什么不好的地方呢?

似乎是本地主机的问题。如果我扫描任何其他IP,而不是本地主机,它会工作得更好。

多线程版本只需两倍的时间就可以完成八倍的工作。你为什么认为这是个问题?@jasonharper我认为时间应该差不多。由于上下文切换,多线程版本应该只需要很少的时间。但没有两次。如果我用time.sleep替换socket,那么行为将完全符合我的预期请参见@adrtam我听说过GIL,但它不能解释为什么用sleep替换sockets例程会改变行为