【问题标题】:Multithreaded Port Scanner多线程端口扫描器
【发布时间】:2013-05-27 20:20:10
【问题描述】:

是的,是的,我知道我可以只使用 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 获取值,而是继续迭代,就好像它已经完成了一样。

我在这里做错了什么?

【问题讨论】:

  • Meaning, it looks like currently the script is not waiting for result to get a value, and just continue iterating on as if it had. 意思是,脚本在多个线程中运行而不是按顺序运行?这不正是你想要的吗?
  • 等待直到q.full 为假。你没有调用函数...

标签: python multithreading sockets python-2.7


【解决方案1】:

您的实际问题已经被一些人回答了,所以这里有一个替代解决方案,使用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'

【讨论】:

    【解决方案2】:

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

    while q.full:
    

    大概你的意思是调用这个函数:

    while q.full():
    

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

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

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

    编辑:s.closes.close() 的问题相同。其他人解决了整个线程池方面的问题。 @Blender 的版本,使用 multiprocessing,要简单得多,因为 multiprocessing 会为您处理。

    【讨论】:

      【解决方案3】:

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

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

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

      • 将端口放入队列
      • 将哨兵放入队列
      • 启动所需数量的线程,让它们从队列中获取端口并处理它们,将结果放入另一个队列中
      • 等待线程终止,在工作线程上调用t.join()
      • 使用结果

      【讨论】:

        【解决方案4】:

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

        您必须等待孩子在 while 正文部分结束时完成。

        我认为:

        threading.wait()
        

        做事。

        【讨论】:

          【解决方案5】:

          试试这个:

          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()
          

          【讨论】:

          • 你的答案应该包含对你的代码的解释和它如何解决问题的描述。
          猜你喜欢
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2023-03-16
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          相关资源
          最近更新 更多