4

好的,所以我做了以下操作,认为如果无法连接它会引发异常:

>>> s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
>>> s.settimeout(0.2)
>>> s.connect(("thisdomaiyndontexistduhh.com", 80))

但没有提出任何例外。如何使用 Python 的 socket 模块测试端口上是否打开了服务器?谢谢!

4

2 回答 2

16

这就是为什么上面的代码永远不会失败的原因。

我的 ISP (Frontier) 配置 DNS,以便对于任何不存在的域,它将返回“198.105.251.114”。因此,他们实际上有一个 Web 服务器在该地址的 80 端口上侦听以显示一些垃圾/垃圾邮件搜索结果。将您的主机更改为使用 8.8.8.8(Google 服务器)作为 DNS,您的上述代码可能会起作用。

鉴于这些类型的“强制网络”很常见,您的代码应该做的第一件事就是确定它是否在这样的网络上。因此,正确的做法是调用 socket.gethostbyname("thisdomaiyndontexistduhh.com")。如果它实际上返回一个值,那么您就知道您在这样的 DNS 服务器后面。因此,然后在要探测的服务器上执行 gethostbyname 调用。如果它返回相同的 DNS 地址,您就知道该服务器不存在。否则,继续进行连接调用以完成测试。

更新:假期我一直在学习Python,所以我以这个问题为借口练习。这是我的代码:

import socket

def DoesServiceExist(host, port):
    captive_dns_addr = ""
    host_addr = ""

    try:
        captive_dns_addr = socket.gethostbyname("BlahThisDomaynDontExist22.com")
    except:
        pass

    try:
        host_addr = socket.gethostbyname(host)

        if (captive_dns_addr == host_addr):
            return False

        s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
        s.settimeout(1)
        s.connect((host, port))
        s.close()
    except:
        return False

    return True
于 2013-01-02T07:19:52.233 回答
0

我发现这个解决方案使用telnetliburllib测试像“https://example.com:6789/test”这样的url中的服务器之间的连接,在这种特殊情况下,我首先寻找端口,然后是模式。我只考虑“http”和“https”,但添加或更改架构(sftp、ssh 等)很容易。

import telnetlib
import time
from urllib.parse import urlsplit

def verify_service(endpoint):

    netloc = "{0.netloc}".format(urlsplit(endpoint))
    scheme = "{0.scheme}".format(urlsplit(endpoint))

    if netloc == '':
        return False

    p = netloc.split(":")

    if len(p) == 2:
        host = p[0]
        port = p[1]
    else:
        host = p[0]
        port = 80 if scheme == "http" else "443"

    try:
        tn = telnetlib.Telnet(host,port)
        time.sleep(1)
    except:
        return False

    return True
于 2020-09-15T13:46:44.363 回答