#!/usr/bin/env python
# -*- coding: iso-8859-1 -*-
"""ping.py
ping.py uses the ICMP protocol's mandatory ECHO_REQUEST
datagram to elicit an ICMP ECHO_RESPONSE from a
host or gateway.
Copyright (C) 2004 - Lars Strand <lars strand at gnist org>;
This program is free software; you can redistribute it and/or
modify it under the terms of the GNU General Public License
as published by the Free Software Foundation; either version 2
of the License, or (at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
Must be running as root, or write a suid-wrapper. Since newer *nix
variants, the kernel ignores the set[ug]id flags on #! scripts for
security reasons
RFC792, echo/reply message:
0 1 2 3
0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
| Type | Code | Checksum |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
| Identifier | Sequence Number |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
| Data ...
+-+-+-+-+-
TODO:
- do not create socket inside 'while' (but if not: ipv6 won't work)
- add support for broadcast/multicast
- add support for own payload string
CHANGELOG:
DONE -->; bugfix from Filip Van Raemdonck mechanix debian org
DONE -->; add more support for modules (raise instead of sys.exit)
DONE -->; locale func names
DONE -->; package def
DONE -->; some code cleanup
"""
import sys
import os
import struct
import array
import time
import select
import binascii
import math
import getopt
import string
import socket
# total size of data (payload)
ICMP_DATA_STR = 56
# initial values of header variables
ICMP_TYPE = 8
ICMP_TYPE_IP6 = 128
ICMP_CODE = 0
ICMP_CHECKSUM = 0
ICMP_ID = 0
ICMP_SEQ_NR = 0
# Package definitions.
__program__ = 'ping'
__version__ = '0.5a'
__date__ = '2004/15/12'
__author__ = 'Lars Strand <lars at unik no>;'
__licence__ = 'GPL'
__copyright__ = 'Copyright (C) 2004 Lars Strand'
def _construct(id, size, ipv6):
"""Constructs a ICMP echo packet of variable size
"""
# size must be big enough to contain time sent
if size < int(struct.calcsize("d")):
_error("packetsize to small, must be at least %d" % int(struct.calcsize("d")))
# construct header
if ipv6:
header = struct.pack('BbHHh', ICMP_TYPE_IP6, ICMP_CODE, ICMP_CHECKSUM, \
ICMP_ID, ICMP_SEQ_NR+id)
else:
header = struct.pack('bbHHh', ICMP_TYPE, ICMP_CODE, ICMP_CHECKSUM, \
ICMP_ID, ICMP_SEQ_NR+id)
# if size big enough, embed this payload
load = "-- IF YOU ARE READING THIS YOU ARE A NERD! --"
# space for time
size -= struct.calcsize("d")
# construct payload based on size, may be omitted :)
rest = ""
if size > len(load):
rest = load
size -= len(load)
# pad the rest of payload
rest += size * "X"
# pack
data = struct.pack("d", time.time()) + rest
packet = header + data # ping packet without checksum
checksum = _in_cksum(packet) # make checksum
# construct header with correct checksum
if ipv6:
header = struct.pack('BbHHh', ICMP_TYPE_IP6, ICMP_CODE, checksum, \
ICMP_ID, ICMP_SEQ_NR+id)
else:
header = struct.pack('bbHHh', ICMP_TYPE, ICMP_CODE, checksum, ICMP_ID, \
ICMP_SEQ_NR+id)
# ping packet *with* checksum
packet = header + data
# a perfectly formatted ICMP echo packet
return packet
def _in_cksum(packet):
"""THE RFC792 states: 'The 16 bit one's complement of
the one's complement sum of all 16 bit words in the header.'
Generates a checksum of a (ICMP) packet. Based on in_chksum found
in ping.c on FreeBSD.
"""
# add byte if not dividable by 2
if len(packet) & 1:
packet = packet + '\0'
# split into 16-bit word and insert into a binary array
words = array.array('h', packet)
sum = 0
# perform ones complement arithmetic on 16-bit words
for word in words:
sum += (word & 0xffff)
hi = sum >> 16
lo = sum & 0xffff
sum = hi + lo
sum = sum + (sum >> 16)
return (~sum) & 0xffff # return ones complement
def pingNode(alive=0, timeout=1.0, ipv6=0, number=sys.maxint, node=None, \
flood=0, size=ICMP_DATA_STR):
"""Pings a node based on input given to the function.
"""
# if no node, exit
if not node:
_error("")
# if not a valid host, exit
if ipv6:
if socket.has_ipv6:
try:
info, port = socket.getaddrinfo(node, None)
host = info[4][0]
# do not print ipv6 twice if ipv6 address given as node
if host == node:
noPrintIPv6adr = 1
except:
_error("cannot resolve %s: Unknow host" % node)
else:
_error("No support for IPv6 on this plattform")
else: # IPv4
try:
host = socket.gethostbyname(node)
except:
_error("cannot resolve %s: Unknow host" % node)
# trying to ping a network?
if not ipv6:
if int(string.split(host, ".")[-1]) == 0:
_error("no support for network ping")
# do some sanity check
if number == 0:
_error("invalid count of packets to transmit: '%s'" % str(a))
if alive:
number = 1
# Send the ping(s)
start = 1; mint = 999; maxt = 0.0; avg = 0.0
lost = 0; tsum = 0.0; tsumsq = 0.0
# tell the user what we do
if not alive:
if ipv6:
# do not print the ipv6 twice if ip adress given as node
# (it can be to long in term window)
if noPrintIPv6adr == 1:
# add 40 (header) + 8 (icmp header) + payload
print "PING %s : %d data bytes (40+8+%d)" % (str(node), \
40+8+size, size)
else:
# add 40 (header) + 8 (icmp header) + payload
print "PING %s (%s): %d data bytes (40+8+%d)" % (str(node), \
str(host), 40+8+size, size)
else:
# add 20 (header) + 8 (icmp header) + payload
print "PING %s (%s): %d data bytes (20+8+%d)" % (str(node), str(host), \
20+8+size, size)
# trap ctrl-d and ctrl-c
try:
# send the number of ping packets as given
while start <= number:
lost += 1 # in case user hit ctrl-c
# create the IPv6/IPv4 socket
if ipv6:
# can not create a raw socket if not root or setuid to root
try:
pingSocket = socket.socket(socket.AF_INET6, socket.SOCK_RAW, \
socket.getprotobyname("ipv6-icmp"))
except socket.error, e:
print "socket error: %s" % e
_error("You must be root (uses raw sockets)" % os.path.basename(sys.argv[0]))
# IPv4
else:
# can not create a raw socket if not root or setuid to root
try:
pingSocket = socket.socket(socket.AF_INET, socket.SOCK_RAW, \
socket.getprotobyname("icmp"))
except socket.error, e:
print "socket error: %s" % e
_error("You must be root (%s uses raw sockets)" % os.path.basename(sys.argv[0]))
packet = _construct(start, size, ipv6) # make a ping packet
# send the ping
try:
pingSocket.sendto(packet,(node,1))
except socket.error, e:
_error("socket error: %s" % e)
# reset values
pong = ""; iwtd = []
# wait until there is data in the socket
while 1:
# input, output, exceptional conditions
iwtd, owtd, ewtd = select.select([pingSocket], [], [], timeout)
break # no data and timout occurred
# data on socket - this means we have an answer
if iwtd: # ok, data on socket
endtime = time.time() # time packet received
# read data (we only need the header)
pong, address = pingSocket.recvfrom(size+48)
lost -= 1 # in case user hit ctrl-c
# examine packet
# fetch TTL from IP header
if ipv6:
# since IPv6 header and any extension header are never passed
# to a raw socket, we can *not* get hoplimit field..
# I hoped that a socket option would help, but it's not
# supported:
# pingSocket.setsockopt(IPPROTO_IPV6, IPV6_RECVHOPLIMIT, 1)
# so we can't fetch hoplimit..
# fetch hoplimit
#rawPongHop = struct.unpack("c", pong[7])[0]
# fetch pong header
pongHeader = pong[0:8]
pongType, pongCode, pongChksum, pongID, pongSeqnr = \
struct.unpack("bbHHh", pongHeader)
# fetch starttime from pong
starttime = struct.unpack("d", pong[8:16])[0]
# IPv4
else:
# time to live
rawPongHop = struct.unpack("s", pong[8])[0]
# convert TTL from 8 bit to 16 bit integer
pongHop = int(binascii.hexlify(str(rawPongHop)), 16)
# fetch pong header
pongHeader = pong[20:28]
pongType, pongCode, pongChksum, pongID, pongSeqnr = \
struct.unpack("bbHHh", pongHeader)
# fetch starttime from pong
starttime = struct.unpack("d", pong[28:36])[0]
# valid ping packet received?
if not pongSeqnr == start:
pong = None
# NO data on socket - timeout waiting for answer
if not pong:
if alive:
print "no reply from %s (%s)" % (str(node), str(host))
else:
print "ping timeout: %s (icmp_seq=%d) " % (host, start)
# do not wait if just sending one packet
if number != 1 and start < number:
time.sleep(flood ^ 1)
start += 1
continue # lost a packet - try again
triptime = endtime - starttime # compute RRT
tsum += triptime # triptime for all packets (stddev)
tsumsq += triptime * triptime # triptime^2 for all packets (stddev)
# compute statistic
maxt = max ((triptime, maxt))
mint = min ((triptime, mint))
if alive:
print str(node) + " (" + str(host) +") is alive"
else:
if ipv6:
# size + 8 = payload + header
print "%d bytes from %s: icmp_seq=%d time=%.5f ms" % \
(size+8, host, pongSeqnr, triptime*1000)
else:
print "%d bytes from %s: icmp_seq=%d ttl=%s time=%.5f ms" % \
(size+8, host, pongSeqnr, pongHop, triptime*1000)
# do not wait if just sending one packet
if number != 1 and start < number:
# if flood = 1; do not sleep - just ping
time.sleep(flood ^ 1) # wait before send new packet
# the last thing to do is update the counter - else the value
# (can) get wrong when computing summary at the end (if user
# hit ctrl-c when pinging)
start += 1
# end ping send/recv while
# if user ctrl-d or ctrl-c
except (EOFError, KeyboardInterrupt):
# if user disrupts ping, it is most likly done before
# the counter get updates - if do not update it here, the
# summary get all wrong.
start += 1
pass
# compute and print som stats
# stddev computation based on ping.c from FreeBSD
if start != 0 or lost > 0: # do not print stats if 0 packet sent
start -= 1 # since while is '<='
avg = tsum / start # avg round trip
vari = tsumsq / start - avg * avg
# %-packet lost
if start == lost:
plost = 100
else:
plost = (lost/start)*100
if not alive:
print "\n--- %s ping statistics ---" % node
print "%d packets transmitted, %d packets received, %d%% packet loss" % \
(start, start-lost, plost)
# don't display summary if 100% packet-loss
if plost != 100:
print "round-trip min/avg/max/stddev = %.3f/%.3f/%.3f/%.3f ms" % \
(mint*1000, (tsum/start)*1000, maxt*1000, math.sqrt(vari)*1000)
pingSocket.close()
def _error(err):
"""Exit if running standalone, else raise an exception
"""
if __name__ == '__main__':
print "%s: %s" % (os.path.basename(sys.argv[0]), str(err))
print "Try `%s --help' for more information." % os.path.basename(sys.argv[0])
sys.exit(1)
else:
raise Exception, str(err)
def _usage():
"""Print usage if run as a standalone program
"""
print """usage: %s [OPTIONS] HOST
Send ICMP ECHO_REQUEST packets to network hosts.
Mandatory arguments to long options are mandatory for short options too.
-c, --count=N Stop after sending (and receiving) 'N' ECHO_RESPONSE
packets.
-s, --size=S Specify the number of data bytes to be sent. The default
is 56, which translates into 64 ICMP data bytes when
combined with the 8 bytes of ICMP header data.
-f, --flood Flood ping. Outputs packets as fast as they come back. Use
with caution!
-6, --ipv6 Ping using IPv6.
-t, --timeout=s Specify a timeout, in seconds, before a ping packet is
considered 'lost'.
-h, --help Display this help and exit
Report bugs to lars [at] gnist org""" % os.path.basename(sys.argv[0])
if __name__ == '__main__':
"""Main loop
"""
# version control
version = string.split(string.split(sys.version)[0][:3], ".")
if map(int, version) < [2, 3]:
_error("You need Python ver 2.3 or higher to run!")
try:
# opts = arguments recognized,
# args = arguments NOT recognized (leftovers)
opts, args = getopt.getopt(sys.argv[1:-1], "hat:6c:fs:", \
["help", "alive", "timeout=", "ipv6", \
"count=", "flood", "packetsize="])
except getopt.GetoptError:
# print help information and exit:
_error("illegal option(s) -- " + str(sys.argv[1:]))
# test whether any host given
if len(sys.argv) >= 2:
node = sys.argv[-1:][0] # host to be pinged
if node[0] == '-' or node == '-h' or node == '--help' :
_usage()
else:
_error("No arguments given")
if args:
_error("illegal option -- %s" % str(args))
# default variables
alive = 0; timeout = 1.0; ipv6 = 0; count = sys.maxint;
flood = 0; size = ICMP_DATA_STR
# run through arguments and set variables
for o, a in opts:
if o == "-h" or o == "--help": # display help and exit
_usage()
sys.exit(0)
if o == "-t" or o == "--timeout": # timeout before "lost"
try:
timeout = float(a)
except:
_error("invalid timout: '%s'" % str(a))
if o == "-6" or o == "--ipv6": # ping ipv6
ipv6 = 1
if o == "-c" or o == "--count": # how many pings?
try:
count = int(a)
except:
_error("invalid count of packets to transmit: '%s'" % str(a))
if o == "-f" or o == "--flood": # no delay between ping send
flood = 1
if o == "-s" or o == "--packetsize": # set the ping payload size
try:
size = int(a)
except:
_error("invalid packet size: '%s'" % str(a))
# just send one packet and say "it's alive"
if o == "-a" or o == "--alive":
alive = 1
# here we send
pingNode(alive=alive, timeout=timeout, ipv6=ipv6, number=count, \
node=node, flood=flood, size=size)
# if we made it this far, do a clean exit
sys.exit(0)
### end
分享到:
相关推荐
这是一个我写的ping程序,使用的是Python语言,作用是,ping一个网段内连续的IP地址,希望对大家有用哦
Python模拟Ping命令实例源码,代码中有注释,可惜是英文的,英文好的下载参考吧,里面就是一具Py文件,主要是实现Ping的机制,演示给Python学习者: __program__ = 'ping' __version__ = '0.5a' __date__ = '...
本篇文章将详细解析如何使用Python实现`ping`命令的功能,以便在自己的应用程序中进行网络探测。 `ping`命令通常用于测试两台计算机之间的网络连接,通过发送ICMP(Internet Control Message Protocol)回显请求...
Python实现的ping工具是利用网络控制消息协议(ICMP)来检查网络连接的可用性和响应时间。ICMP是一种网络层协议,主要用于在IP网络中发送控制消息,如错误报告或查询信息。在这个项目中,Python被用作编程语言,通过...
icmp,tcpping工具源码。源码和exe工具,离线运行。
2. Python编程语言:Python是一种易于学习且功能强大的编程语言,在网络编程、数据处理和自动化等领域具有广泛应用。本项目使用Python实现了SDN控制器、流量监控模块和控制策略。 3. Mininet:Mininet是一个用于...
高职的也有 但是包含的不算多 包含: 端口扫描,arp dos,arp欺骗,arp数据监控,dic字典,dos land,ftp连接,mac地址泛红,mssql爆破,PCAP数据监控,ping扫描,socket远连,ssh连接,tcpdos
6. **Python编程实践**:实验报告的Python源码格式规范,注释清晰,是学习Python编程和网络编程的优秀案例。Python语言简洁明了,非常适合初学者理解和实践。 通过这份实验报告和源码,读者不仅可以加深对计算机...
标题中的“PING程序源码”指的是网络中常用的网络诊断工具——PING命令的源代码实现。PING,全称为Packet Internet Groper(互联网包探测器),它是一个利用ICMP协议在网络中发送回声请求并接收回声应答的工具,用于...
该项目是一款基于Python与Go语言开发的多进程批量Ping检测工具源码,共计22个文件,涵盖3个Python脚本、2个Git忽略配置、2个XML配置文件、2个文本文件、1个Idea项目文件以及一系列的DEBIAN相关脚本文件。此工具利用...
基于树莓派的多功能寝室监控系统python源码+项目操作说明.zip 这个标题看起来就很像大学生的课设,但是其实不是,因为我是小学生,所以是小学生的课设。 大家在寝室里经常会遇到一些难题,比如寝室太冷、太热、太吵...
今天我们将聚焦于"PingPong-源码.rar"这个压缩包,它包含了一个名为"PingPong-源码.zip"的文件,这很可能是某个乒乓球游戏的源代码。通过分析这个游戏的源代码,我们可以深入理解游戏开发的基本原理,特别是涉及到...
在Python中,可以使用`socket`库或者第三方的`ping3`库来实现;在C#中,可以使用`System.Net.NetworkInformation.Ping`类。 3. **响应时间计算**:每次ping请求成功后,源码会计算并记录从发送到接收回显请求的时间...
是一个python多线程ping和arpping扫描工具实现的源码。 这里还有待修改的地方,例如:希望能扫描一个地址范围,使用IPy模块可以实现对ip地址的处理,实现扫描一个网段的ip,不用像现在实现的这么笨拙。应该有更巧妙...
当你解压后,可以通过阅读源码了解其内部实现细节,或者参考文档学习如何在项目中集成和使用NAPALM。 总的来说,Python-NAPALM是一个强大的工具,它为网络自动化提供了标准化的接口,降低了跨平台网络管理的复杂度...
java版erp管理系统源码 title python-open-source-projects 做过python + django开发。 关注了很长一段时间的python开源项目。 收集起来。 供日后参考。 监控系统 序号 名称 项目地址 简介 1 sd-agent-plugin-...
本项目是一个基于Python和Django框架的CRM服务器监控系统,主要功能是监控CRM的Linux服务器健康程度,使用Selenium对指定网页进行前端性能测试,对指定服务器进行iPerf测试和Ping测试,提供REST API用于命令服务器...
对于端口扫描,通常会发送一个SYN包(TCP扫描)或一个ICMP请求(ping扫描)。 3. **多线程与并发**:为了加快扫描速度,项目可能采用了多线程技术。`threading`模块可以创建多个线程,每个线程负责扫描不同的IP地址...
资源分类:Python库 所属语言:Python 使用前提:需要解压 资源全名:ping_cmd-1.2-py3-none-any.whl 资源来源:官方 安装方法:https://lanzao.blog.csdn.net/article/details/101784059
"源码"表明提供了实现这一功能的编程代码,可能是用C++、Java、Python等语言编写,用户可以查看和学习,甚至进行修改和扩展。"网络通信类"可能指的是该程序属于网络通信软件类别,涉及到网络协议、数据传输和错误...