在Python中,是否有一种方法可以通过ICMP来ping服务器,如果服务器响应则返回TRUE,如果没有响应则返回FALSE ?


当前回答

我自己的方法结合了上面的几个答案:


def ping(host, show_log=False, package_count=1):
    ping.param = "-n" if platform.system().lower() == 'windows' else "-c"
    result = subprocess.run(['ping', ping.param, str(package_count), host],
                            stdout=subprocess.PIPE,
                            stderr=subprocess.STDOUT)
    output = result.stdout
    if show_log:
        print('return code: ', result.returncode)
        print(output.decode("utf-8"))
    return result.returncode == 0 and (b'TTL=' in output or b'ttl=' in output)

在OSX Monterey上测试。

其他回答

import os #to get clear screen
import subprocess as sp #to get system ping
os.system("clear") #clear screen
print('Wait or Press Ctrl+Z to Terminate\n') #notice to terminate or wait
for i in range(255): #0 to 255 loop
    ip='192.168.1.'+str(i) #concatenating str and int
    s,r=sp.getstatusoutput("ping -c1 -w2 " + ip) #ping and store status in s
    if s==0: #if status is 0 equal to pass
        print(ip+" is UP ✓ ") #output
    else: #if status is not 0 equal to fail
        pass #skip and try next ip from loop

我需要一个更快的ping扫描,我不想使用任何外部库,所以我决定使用内置的asyncio来实现并发。

此代码需要python 3.7+,仅在Linux上制作和测试。它不能在Windows上工作,但我相信你可以很容易地将其更改为在Windows上工作。

我不是asyncio方面的专家,但我使用了这篇很棒的文章,用并发性加速你的Python程序,我想出了这些代码行。我试图使它尽可能简单,所以很可能您需要添加更多的代码来满足您的需求。

它不会返回true或false,我认为让它打印响应ping请求的IP会更方便。我认为这是相当快的,在近10秒内ping 255个ip。

#!/usr/bin/python3

import asyncio

async def ping(host):
    """
    Prints the hosts that respond to ping request
    """
    ping_process = await asyncio.create_subprocess_shell("ping -c 1 " + host + " > /dev/null 2>&1")
    await ping_process.wait()

    if ping_process.returncode == 0:
        print(host)
    return 


async def ping_all():
    tasks = []

    for i in range(1,255):
        ip = "192.168.1.{}".format(i)
        task = asyncio.ensure_future(ping(ip))
        tasks.append(task)

    await asyncio.gather(*tasks, return_exceptions = True)

asyncio.run(ping_all())

样例输出:

192.168.1.1
192.168.1.3
192.168.1.102
192.168.1.106
192.168.1.6

请注意,IP不是按顺序排列的,因为IP在它响应时就会打印出来,所以先响应的就会先打印出来。

如果您的服务器不支持ICMP(防火墙可能会阻止它),它很可能仍然在TCP端口上提供服务。在这种情况下,你可以像这样执行TCP ping1(平台独立,无需安装额外的python模块):

import socket

def isReachable(ipOrName, port, timeout=2):
    s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
    s.settimeout(timeout)
    try:
        s.connect((ipOrName, int(port)))
        s.shutdown(socket.SHUT_RDWR)
        return True
    except:
        return False
    finally:
        s.close()

代码从这里开始只做了轻微的修改。


1 TCP ping并不真正存在,因为ping是在ISO/OSI第三层用ICMP执行的。TCP ping在ISO/OSI第4层执行。它只是试图以最基本的方式连接到TCP端口,即不传输任何数据,而是在连接后立即关闭连接。

使用这个,它在python 2.7上测试过,工作很好,如果成功,它返回以毫秒为单位的ping时间,失败时返回False。

import platform,subproccess,re
def Ping(hostname,timeout):
    if platform.system() == "Windows":
        command="ping "+hostname+" -n 1 -w "+str(timeout*1000)
    else:
        command="ping -i "+str(timeout)+" -c 1 " + hostname
    proccess = subprocess.Popen(command, stdout=subprocess.PIPE)
    matches=re.match('.*time=([0-9]+)ms.*', proccess.stdout.read(),re.DOTALL)
    if matches:
        return matches.group(1)
    else: 
        return False

我的解决方法是:

def ping(self, host):
    res = False

    ping_param = "-n 1" if system_name().lower() == "windows" else "-c 1"

    resultado = os.popen("ping " + ping_param + " " + host).read()

    if "TTL=" in resultado:
        res = True
    return res

“TTL”是判断ping是否正确的方法。 Saludos