为什么 socket.connect() 在 Python 3.4 的循环中使用时停止工作?

Why does socket.connect() stop working when used within a loop in Python 3.4?

我刚开始学习编程 python,并且一直在学习创建简单端口扫描器的教程,以便学习套接字编程。当我手动输入单次迭代的所有代码时,我能够成功连接到本地主机,但是如果我采用相同的代码,并使用 try/except 在 for 循环中应用它,我会立即得到异常范围内的每个端口,即使我知道某些端口是打开的。我相信我已经将问题隔离到 socket.connect() 因为我在下面输入了我知道永远不会执行的代码。

我可以输入下面的代码,得到成功return:

import socket
s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
s.settimeout(10)
port = 22
s.connect(('127.0.0.1', port))
s.send(b'test')
banner = s.recv(1024)
print(banner)
s.close()

return秒:

b'SSH-2.0-OpenSSH_6.2\r\n'

Process finished with exit code 0

但是,一旦我获取该代码并将其移动到以端口号作为迭代器的 for 循环中,它就会停止工作。

import socket
s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
s.settimeout(10)
for port in range(1,26):
    print("[+]Attempting to connect to : " + str(port))
    try:
      s.connect(('127.0.0.1', port))
      s.send(b'test')
      banner = s.recv(1024)
      s.close()
      if banner:
        print("Port " + port + "is Open: " + banner)
    except: print("[+]Port " + str(port) + " is closed")  

returns:

[+]Attempting to connect to : 1
[+]Port 1 is closed
[+]Attempting to connect to : 2
[+]Port 2 is closed
[+]Attempting to connect to : 3
[+]Port 3 is closed
....ETC....ETC....ETC....
[+]Attempting to connect to : 24
[+]Port 24 is closed
[+]Attempting to connect to : 25
[+]Port 25 is closed

即使我知道端口 22 已打开并在本地主机上侦听。 (即我可以毫无问题地通过 ssh 连接到 127.0.0.1)。我已经尝试了所有我能想到的无济于事,包括通过使用内部 int() 函数手动将端口的数据类型更改为 int,我已经尝试了 socket.connect_ex 对象等。我已经还将代码放在 socket.connect 语句的正下方,看看它是否出现,但它从来没有出现。

The Zen of Python 状态:

Errors should never pass silently.
Unless explicitly silenced.

只是您没有消除错误,而只是将其替换为无法描述实际发生情况的消息:

>>> "Port" + 1
Traceback (most recent call last):
  File "<pyshell#15>", line 1, in <module>
    "Port "+1
TypeError: Can't convert 'int' object to str implicitly

如果打开端口 1 有效,但关闭套接字后,您将无法连接到其他任何东西:

>>> a = socket.socket()
>>> a.close()
>>> a.connect(("www.python.com",80))
Traceback (most recent call last):
  File "<pyshell#18>", line 1, in <module>
    a.connect(("www.python.com",80))
OSError: [Errno 9] Bad file descriptor

因此您需要在循环内创建一个新套接字才能正常工作,但最重要的是:您需要限制捕获的错误:

try:
    #if this is the only line you expect to fail, then it is the only line in the try
    s.connect(('127.0.0.1', port))
except ConnectionError: 
    #if a ConnectionError is the only one you expect, it is the only one you catch
    print("[+]Port " + str(port) + " is closed")
else: #if there was no error
    s.send(b'test')
    banner = s.recv(1024)
    s.close()
    if banner:
        print("Port " + port + "is Open: " + banner)

然后你会看到你得到的实际错误,而不是猜测出了什么问题,这也违反了 The Zen of Python:

In the face of ambiguity, refuse the temptation to guess.