2016-02-22 118 views
1

我新的Python3.5,和異步一般可以用Python 2.7未成年人使用雙絞線的除外。我正在將其構建到一個更大的應用程序中,我需要一小部分來執行TCP端口掃描,而不是一個單一的框架。Python3.5 ASYNCIO 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掃描儀?

回答

2

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塊捕捉異常的其餘部分,包括拒絕最常見的連接。

+0

這有一定道理,但我現在收到幾百個「任務被摧毀,但它正在等待!」錯誤。當我減少我使用的端口數量時,它將起作用。這是否與select()中併發fileno的數量有關?我之前遇到過這種情況,我相信這是關於Windows的事情,只允許其中的1024個...... – Goodies

+0

這就是我寫「(或某個部分)」的原因。解決方法是增加'超時'(實際上它不是一個好主意),將它分成塊(可能是300個併發conn) – kwarunek