【问题标题】:Python3.5 Asyncio TCP ScannerPython3.5 异步 TCP 扫描器
【发布时间】:2016-02-22 00:26:27
【问题描述】:

我是 Python3.5 的新手,除了在 Python 2.7 中少量使用 Twisted 外,我一般都是异步的。我正在将它构建到一个更大的应用程序中,我需要一小部分,而不是一个单一的框架,来执行 TCP 端口扫描。

import asyncio
from random import SystemRandom

def run(task, *, loop=None):
    if loop is None:
        loop = asyncio.get_event_loop()
    return loop.run_until_complete(asyncio.ensure_future(task, loop=loop))

async def scanner(ip, port, loop=None):
    fut = asyncio.open_connection(ip, port, loop=loop)
    try:
        reader, writer = await asyncio.wait_for(fut, timeout=0.5) # This is where it is blocking?
        print("{}:{} Connected".format(ip, port))
    except asyncio.TimeoutError:
        pass

def scan(ips, ports, randomize=False):
    if randomize:
        rdev = SystemRandom()
        ips = rdev.shuffle(ips)
        ports = rdev.shuffle(ports)
    for port in ports:
        for ips in ips:
            run(scanner(ip, port))

 ips = ["192.168.0.{}".format(i) for i in range(1, 255)]
 ports = [22, 80, 443, 8080]
 scan(ips, ports)

这仍然需要与单个线程一样长的时间。我怎样才能把它变成一个异步 TCP 扫描器?

【问题讨论】:

    标签: python-3.x asynchronous tcp python-asyncio


    【解决方案1】:

    run_until_complete 正在阻塞,执行停止并等待直到第一次扫描结束,然后是下一次...

    您应该安排所有(或部分)任务并使用wait 等待所有任务。

    import asyncio
    from random import SystemRandom
    
    def run(tasks, *, loop=None):
        if loop is None:
            loop = asyncio.get_event_loop()
        # waiting for all tasks
        return loop.run_until_complete(asyncio.wait(tasks))
    
    async def scanner(ip, port, loop=None):
        fut = asyncio.open_connection(ip, port, loop=loop)
        try:
            reader, writer = await asyncio.wait_for(fut, timeout=0.5) # This is where it is blocking?
            print("{}:{} Connected".format(ip, port))
        except asyncio.TimeoutError:
            pass
        # handle connection refused and bunch of others
        except Exception as exc:
            print('Error {}:{} {}'.format(ip, port, exc))
    
    def scan(ips, ports, randomize=False):
        loop = asyncio.get_event_loop()
        if randomize:
            rdev = SystemRandom()
            ips = rdev.shuffle(ips)
            ports = rdev.shuffle(ports)
    
        # let's pass list of task, not only one
        run([scanner(ip, port) for port in ports for ip in ips])
    
    ips = ["192.168.0.{}".format(i) for i in range(1, 255)]
    ports = [22, 80, 443, 8080]
    scan(ips, ports)
    

    我还添加了except 块来捕获其余异常,包括最常见的连接被拒绝。

    【讨论】:

    • 这确实有道理,但是我现在收到数百个“任务已被破坏,但它正在等待!”错误。当我减少我正在使用的端口数量时,它会起作用。这是否与 select() 中的并发文件数有关?我之前遇到过这个问题,我相信这是关于 Windows 只允许其中 1024 个...
    • 这就是我写“(或某些部分)”的原因。解决办法是增加timeout(其实不是个好主意),拆分成块(可能300个并发conn)
    猜你喜欢
    • 2017-01-19
    • 2023-03-16
    • 1970-01-01
    • 2014-04-24
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2014-02-15
    • 2011-05-26
    相关资源
    最近更新 更多