python - 如何在多线程应用程序中连接python套接字
问题描述
我想写一个简单的端口扫描器。这样做如下:
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()
在我的 8 核 i7 上,它占用大约 200 毫秒。如果我在这样的 1 个线程上做同样的事情:
with Scanner() as scanner:
ports = scanner.scan(1)
它占用100毫秒。
我不明白为什么我会得到这样的结果。为什么在 1 个线程中扫描 1000 个端口所需的时间比在 8 个线程中扫描 1000 个端口所需的时间少 2 倍?请解释一下。
如果我用简单的 time.sleep 替换套接字的东西, UPD它将按我的预期工作 - 多线程模式与单线程占用相同的时间,那么套接字有什么不好的呢?
解决方案
似乎是本地主机问题。如果我扫描任何其他 IP,而不是本地主机,它会更好。
推荐阅读
- python-sphinx - 如何在 sphinx-doc 的 restructuredtext 中指定阿拉伯语文本?
- c# - 如何以可读格式将excel文件上传到azure blob?
- python - 基本 Pytorch 张量乘法和加法
- android - 如何使用 MediaColumns#IS_PENDING 将位图转换为 Uri?
- php - php7.4 扩展 amqp 已安装但未加载
- bash - 无法使用“未设置”操作数组
- ruby-on-rails - 未初始化的常量 (NameError) Ruby
- django - 谷歌云数据存储回滚之前保存的行
- python-3.x - groupby value_counts 存储在数据框中
- javascript - HTML5 Canvas Resize - 可以控制或预测内存问题吗?