【转】python版的ping
Ping的原理就是向目标主机发送一个ICMP_ECHO请求(type=8),对方如果回复ICMP_ECHOPLY(type=0).则说明目标主机是可以存活的.但是目前很多防火墙可能对ICMP报文做了过滤,于是在后面的代码中又添加了利用知名端口去连接检测目标主机是否存活的.这仅是一个相对简单的实现,探测目标主机是否存活在防火墙的重重过滤下,还需要一个更好的更高效的处理方法.
该Ping程序支持简短参数。传递包括-c制定ping次数,-d ping时发送的数据等。
#!/usr/bin/env python
#coding:utf-8
import dpkt
import random
import socket
import time
import sys
import getopt
SCRIPT_EXP = "Ping Python Script With Tradiontal Method"
AUTHOR = "Zimilo"
AUTHOR_EMAIL = "Instance@9.cn"
AUTHOR_MSN = "Instance@9.cn"
VERSION = "0.0.1"
LAST_UPDATED = "2009/07/29"
DEFAULT_SEND_COUNT = 4
DEFAULT_SEND_DATA = "Zimilo"
count = DEFAULT_SEND_COUNT
data = DEFAULT_SEND_DATA
def print_welcome():
print "*"*50
print SCRIPT_EXP
print "Author:",AUTHOR
print "Email:",AUTHOR_EMAIL
print "MSN:",AUTHOR_MSN
print "Version:",VERSION
print "Last Update:",LAST_UPDATED
print "*"*50
def print_ping_header(dst, data):
now = time.localtime(time.time())
strtime = str(now.tm_year)+'/'+str(now.tm_mon)+'/'+str(now.tm_mday)+" "+str(now.tm_hour)+':'+str(now.tm_min)+':'+str(now.tm_sec)
print "-"*50
print "Starting at: %s\nPinging %s with data: \"%s\"" % (strtime, dst, data)
print "-"*50
def exit_program():
print "*"*50
sys.exit(1)
def print_version():
print_welcome()
print "Current Version:", VERSION
exit_program()
def print_help():
print_welcome()
print "Usage: ping.py [options] host"
exit_program()
def ping(host, count, data):
try:
dst = socket.gethostbyname(host)
except socket.gaierror:
print "host not found"
sys.exit(1)
data = data
print_welcome()
print_ping_header(dst, data)
echo = dpkt.icmp.ICMP.Echo()
echo.id = random.randint(0, 0xffff)
echo.seq = random.randint(0, 0xffff)
echo.data = data
icmp = dpkt.icmp.ICMP()
icmp.type = dpkt.icmp.ICMP_ECHO
icmp.data = echo
for i in range(0, count):
s = socket.socket(socket.AF_INET, socket.SOCK_RAW, dpkt.ip.IP_PROTO_ICMP)
s.settimeout(3)
start = time.time()
s.sendto(str(icmp), (dst, 0))
try:
reply = s.recv(0xffff)
except:
flag = False
print "Request timeout"
continue
used = (time.time() - start)*1000
ip = dpkt.ip.IP(reply)
if ip.icmp.type == 0 or (ip.icmp.type==8 and host == "localhost"):
print '%d bytes from %s: icmp_seq=%d ip_id=%d ttl=%d time=%.3fms' % (len(ip.icmp), dst, ip.icmp.echo.seq, ip.id, ip.ttl, used)
else:
print ip.icmp.type
time.sleep(1)
s.close()
if __name__ == "__main__":
try:
opts, args = getopt.getopt(sys.argv[1:], "hvc:d:")
except getopt.GetoptError:
print_help()
for o, a in opts:
if o == "-v":
print_version()
elif o == "-h":
print_help()
elif o == "-c":
count = int(a)
elif o == "-d":
data = a
else:
print_help()
host = ''.join(args)
if len(host) < 1:
print_help()
ping(host, count, data)
以下是运行示例.
**************************************************
Ping Python Script With Tradiontal Method
Author: Zimilo
Email: Instance@9.cn
MSN: Instance@9.cn
Version: 0.0.1
Last Update: 2009/07/29
**************************************************
————————————————–
Starting at: 2011/11/30 23:42:50
Pinging 61.135.169.105 with data: “Zimilo”
————————————————–
14 bytes from 61.135.169.105: icmp_seq=59086 ip_id=0 ttl=50 time=98.975ms
14 bytes from 61.135.169.105: icmp_seq=59086 ip_id=0 ttl=50 time=99.826ms
14 bytes from 61.135.169.105: icmp_seq=59086 ip_id=0 ttl=50 time=96.404ms
14 bytes from 61.135.169.105: icmp_seq=59086 ip_id=0 ttl=50 time=96.575ms
需要注意的是icmp需要root权限的哦。