是的,是的,我知道我可以使用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
获取值,而是继续迭代,就像它有了一样。
我在这里做错了什么?
答案 0 :(得分: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'
答案 1 :(得分:2)
这里有几个问题,第一个是:
while q.full:
据推测,你打算调用这个函数:
while q.full():
但是你有一个无限的队列(你创建它没有maxsize),所以它永远不会满;所以如果你做了那个改变,它根本不会调用scan()。
假设您以其他方式解决此问题(例如,使用q.empty()
),如果range(threads)
不能均匀划分队列中的项目,会发生什么?例如,假设您使用3个线程并将端口号1,2,3和4放入q
。您将在第一次旅行中通过外部q.get()
呼叫while
三次(获得1,2和3),然后在第二次旅行中再次呼叫三次 - 但它只有一次其中包含更多价值,4
,因此在此之后调用q.get()
会等待某人执行q.put()
,您将陷入困境。
换句话说,你需要改写逻辑。
修改:与s.close
vs s.close()
相同的问题。其他人解决了整个线程方面的问题。使用multiprocessing
的@Blender版本要简单得多,因为multiprocessing
会为你处理这个问题。
答案 2 :(得分:1)
您的代码存在一些问题。首先,while循环一直持续到q.full
,这是一个函数,是假的。但实际上没有必要在主线程中循环。
我会将sentinel值添加到队列的末尾,每个工作线程一个。当工作线程获得哨兵时,它退出其处理循环。这样您就不必守护线程了。
所以你的代码应该是:
t.join()
答案 3 :(得分:0)
嗯,你必须知道只需遍历线程数范围内的数字并执行线程,就不会保留所需线程的数量。它只循环4次,创建4个线程,再次循环并进入另一个相同的循环并创建另外4个而不确定那些4完成了他们的任务,因此当您将打印件放入扫描功能时,您将获得大量消息。
您必须等待孩子们在身体部分结束时完成。
我想:
threading.wait()
做到了。
答案 4 :(得分:-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()