2

是的,是的,我知道我可以只使用 nmap,但我想自己尝试一下。

我正在尝试编写一个线程脚本来查找目标 IP 地址上的开放端口。这就是我现在所拥有的:

import socket, Queue
from threading import Thread


print "Target to scan: "
targetIP = raw_input("> ")
print "Number of threads: "
threads = int(raw_input("> "))


q = Queue.Queue()

# Fill queue with port numbers
for port in range(1, 1025):
    q.put(port)


def scan(targetIP, port):
    try:
        s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
        s.settimeout(4)
        result = s.connect_ex((targetIP, port))
        if result == 0:
            print 'Port {0} is open'.format(port)
        s.close
        q.task_done()



while q.full:
    for i in range(threads):
        port = q.get()
        t = Thread(target=scan, args =(targetIP, port))
        t.daemon = True
        t.start()

但是我有几个问题:

1)当我按原样运行它时,它将遍历端口队列,然后挂起,while即使队列为空,也永远不会脱离循环。

2)如果我添加一个打印行来scan查看发生了什么,基本上在开头添加一个“扫描端口 X”行,print result在末尾添加一行,stdout 会被队列中所有端口的“扫描端口”行淹没,然后打印结果行。意思是,看起来当前脚本并没有等待result获取值,而是继续迭代,就好像它有一样。

我在这里做错了什么?

4

5 回答 5

4

一些人已经回答了您的实际问题,所以这里有一个替代解决方案,multiprocessing.Pool而不是threading

import socket

from multiprocessing import Pool

def scan(arg):
    target_ip, port = arg

    sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
    sock.settimeout(2)

    try:
        sock.connect((target_ip, port))
        sock.close()

        return port, True
    except (socket.timeout, socket.error):
        return port, False

if __name__ == '__main__':
    target_ip = raw_input('Target IP: ')
    num_procs = int(raw_input('Number of processes: '))

    ports = range(1, 1025)
    pool = Pool(processes=num_procs)

    for port, status in pool.imap_unordered(scan, [(target_ip, port) for port in ports]):
        print port, 'is', 'open' if status else 'closed'
于 2013-05-27T20:41:14.173 回答
2

你这里有几个问题,第一个是:

while q.full:

大概您打算调用该函数:

while q.full():

但是你有一个无限队列(你创建它时没有 maxsize),所以它永远不会满;因此,如果您进行更改,它根本不会调用 scan() 。

假设您以其他方式解决此问题(例如,使用q.empty()),如果range(threads)没有均匀划分队列中的项目会发生什么?例如,假设您使用 3 个线程并将端口号 1、2、3 和 4 放入q. 您将q.get()在第一次通过外部调用时调用 3 次(获取 1、2 和 3)while,然后在第二次调用中再次调用它 3 次——但它只有一个值4,所以调用q.get()之后将等待某人执行 a q.put(),您将被卡住。

换句话说,您需要重写逻辑。

编辑:与s.closevs相同的问题s.close()。其他人解决了整个线程池方面的问题。@Blender 的版本 usingmultiprocessing更简单,因为multiprocessing它会为您处理。

于 2013-05-27T20:34:27.497 回答
1

您的代码存在一些问题。首先,while 循环一直持续到q.full,它是一个函数,是虚假的。但实际上没有必要在你的主线程中循环。

我会将哨兵值添加到队列的末尾,每个工作线程一个。当工作线程获得哨兵时,它会退出其处理循环。这样你就不必守护线程。

所以你的代码应该是这样的:

  • 将端口放入队列
  • 将哨兵放入队列
  • 启动所需数量的线程,让它们从队列中获取端口并处理它们,将结果放入另一个队列
  • 等待线程终止,调用t.join()工人
  • 使用结果
于 2013-05-27T20:38:48.617 回答
0

好吧,您必须知道,仅通过迭代线程数范围内的数字并执行线程,您不会保留所需的线程数。它只是循环 4 次,创建 4 个线程,再次循环并进入另一个相同的循环并创建另一个 4,但不确定这 4 个是否已完成任务,因此当您将打印件放入扫描功能时,您会收到大量消息。

您将不得不等待孩子们在 while 正文部分结束时完成。

我认为:

threading.wait()

做这件事。

于 2013-05-27T20:34:08.420 回答
-1

试试这个:

import socket
import threading
from queue import Queue

print_lock = threading.Lock()

target = 'pythonprogramming.net'

def portscan(port):
    s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
    try:
        con = s.connect((target,port))
        with print_lock:
            print('port',port,'is open!')
        con.close()
    except:
        pass

def threader():
    while True:
        worker = q.get()
        portscan(worker)
        q.task_done()

q = Queue()

for x in range(30):
    t = threading.Thread(target=threader)
    t.daemon = True
    t.start()


for worker in range(1,10000):
    q.put(worker)

q.join()
于 2014-09-04T01:07:08.613 回答