python实现一个简单的ping工具方法


Posted in Python onJanuary 31, 2019

继上一篇计算checksum校验和,本章通过socket套接字,struct字节打包成二进制,select返回套接字的文件描述符的结合,实现一个简单的ping工具。

#!/usr/bin/python3.6.4
#!coding:utf-8
__author__ = 'Rosefinch'
__date__ = '2018/5/31 22:27'

import time
import struct
import socket
import select
import sys

def chesksum(data):
  """
  校验
  """
  n = len(data)
  m = n % 2
  sum = 0 
  for i in range(0, n - m ,2):
    sum += (data[i]) + ((data[i+1]) << 8)#传入data以每两个字节(十六进制)通过ord转十进制,第一字节在低位,第二个字节在高位
  if m:
    sum += (data[-1])
  #将高于16位与低16位相加
  sum = (sum >> 16) + (sum & 0xffff)
  sum += (sum >> 16) #如果还有高于16位,将继续与低16位相加
  answer = ~sum & 0xffff
  #主机字节序转网络字节序列(参考小端序转大端序)
  answer = answer >> 8 | (answer << 8 & 0xff00)
  return answer 

  '''
  连接套接字,并将数据发送到套接字
  '''
def raw_socket(dst_addr,imcp_packet):
  rawsocket = socket.socket(socket.AF_INET,socket.SOCK_RAW,socket.getprotobyname("icmp"))
  send_request_ping_time = time.time()
  #send data to the socket
  rawsocket.sendto(imcp_packet,(dst_addr,80))
  return send_request_ping_time,rawsocket,dst_addr

  '''
  request ping
  '''
def request_ping(data_type,data_code,data_checksum,data_ID,data_Sequence,payload_body):
  #把字节打包成二进制数据
  imcp_packet = struct.pack('>BBHHH32s',data_type,data_code,data_checksum,data_ID,data_Sequence,payload_body)
  icmp_chesksum = chesksum(imcp_packet)#获取校验和
  imcp_packet = struct.pack('>BBHHH32s',data_type,data_code,icmp_chesksum,data_ID,data_Sequence,payload_body)
  return imcp_packet
  '''
  reply ping
  '''
def reply_ping(send_request_ping_time,rawsocket,data_Sequence,timeout = 2):
  while True:
    started_select = time.time()
    what_ready = select.select([rawsocket], [], [], timeout)
    wait_for_time = (time.time() - started_select)
    if what_ready[0] == []: # Timeout
      return -1
    time_received = time.time()
    received_packet, addr = rawsocket.recvfrom(1024)
    icmpHeader = received_packet[20:28]
    type, code, checksum, packet_id, sequence = struct.unpack(
      ">BBHHH", icmpHeader
    )
    if type == 0 and sequence == data_Sequence:
      return time_received - send_request_ping_time
    timeout = timeout - wait_for_time
    if timeout <= 0:
      return -1

  '''
  实现 ping 主机/ip
  '''
def ping(host):
  data_type = 8 # ICMP Echo Request
  data_code = 0 # must be zero
  data_checksum = 0 # "...with value 0 substituted for this field..."
  data_ID = 0 #Identifier
  data_Sequence = 1 #Sequence number
  payload_body = b'abcdefghijklmnopqrstuvwabcdefghi' #data
  dst_addr = socket.gethostbyname(host)#将主机名转ipv4地址格式,返回以ipv4地址格式的字符串,如果主机名称是ipv4地址,则它将保持不变
  print("正在 Ping {0} [{1}] 具有 32 字节的数据:".format(host,dst_addr))
  for i in range(0,4):
    icmp_packet = request_ping(data_type,data_code,data_checksum,data_ID,data_Sequence + i,payload_body)
    send_request_ping_time,rawsocket,addr = raw_socket(dst_addr,icmp_packet)
    times = reply_ping(send_request_ping_time,rawsocket,data_Sequence + i)
    if times > 0:
      print("来自 {0} 的回复: 字节=32 时间={1}ms".format(addr,int(times*1000)))
      time.sleep(0.7)
    else:
      print("请求超时。")

if __name__ == "__main__":
  if len(sys.argv) < 2:
    sys.exit('Usage: ping.py <host>')
  ping(sys.argv[1])
>python .\Ping_tool.py www.csdn.net
正在 Ping www.csdn.net [47.95.164.112] 具有 32 字节的数据:
来自 47.95.164.112 的回复: 字节=32 时间=39ms
来自 47.95.164.112 的回复: 字节=32 时间=40ms
来自 47.95.164.112 的回复: 字节=32 时间=40ms
来自 47.95.164.112 的回复: 字节=32 时间=39ms

引用:

https://docs.python.org/3/library/socket.html

https://docs.python.org/3/library/select.html#select.select

https://docs.python.org/3/library/struct.html

以上这篇python实现一个简单的ping工具方法就是小编分享给大家的全部内容了,希望能给大家一个参考,也希望大家多多支持三水点靠木。

Python 相关文章推荐
Python实现句子翻译功能
Nov 14 Python
关于Django ForeignKey 反向查询中filter和_set的效率对比详解
Dec 15 Python
python实现自动解数独小程序
Jan 21 Python
详解python中的time和datetime的常用方法
Jul 08 Python
Django ORM 常用字段与不常用字段汇总
Aug 09 Python
python logging日志模块原理及操作解析
Oct 12 Python
pytorch masked_fill报错的解决
Feb 18 Python
Python MySQLdb 执行sql语句时的参数传递方式
Mar 04 Python
Python无头爬虫下载文件的实现
Apr 02 Python
python 实现两个变量值进行交换的n种操作
Jun 02 Python
python机器学习实现oneR算法(以鸢尾data为例)
Mar 03 Python
Python OpenCV形态学运算示例详解
Apr 07 Python
Python获取网段内ping通IP的方法
Jan 31 #Python
Python实现删除排序数组中重复项的两种方法示例
Jan 31 #Python
python重试装饰器的简单实现方法
Jan 31 #Python
Python实现合并两个有序链表的方法示例
Jan 31 #Python
Django 日志配置按日期滚动的方法
Jan 31 #Python
Python类的继承用法示例
Jan 31 #Python
判断python对象是否可调用的三种方式及其区别详解
Jan 31 #Python
You might like
各种咖啡的英文名子是什么
2021/03/03 新手入门
php之对抗Web扫描器的脚本技巧
2008/10/01 PHP
利用Memcached在php下实现session机制 替换PHP的原生session支持
2010/08/21 PHP
PHP中数组合并的两种方法及区别介绍
2012/09/14 PHP
php源代码安装常见错误与解决办法分享
2013/05/28 PHP
ThinkPHP使用PHPExcel实现Excel数据导入导出完整实例
2014/07/22 PHP
php 使用redis锁限制并发访问类示例
2016/11/02 PHP
PHP children()函数讲解
2019/02/03 PHP
Laravel框架运行出错提示RuntimeException No application encryption key has been specified.解决方法
2019/04/02 PHP
jquery实现的让超出显示范围外的导航自动固定屏幕最顶上
2011/09/22 Javascript
js调试系列 控制台命令行API使用方法
2014/06/18 Javascript
jQuery简单实现上下,左右滑动的方法
2016/06/01 Javascript
js实现图片左右滚动效果
2017/02/27 Javascript
很棒的vue弹窗组件
2017/05/24 Javascript
详解Webpack实战之构建 Electron 应用
2017/12/25 Javascript
Angular实现点击按钮后在上方显示输入内容的方法
2017/12/27 Javascript
Vue单页面应用保证F5强刷不清空数据的解决方案
2018/01/31 Javascript
用node开发并发布一个cli工具的方法步骤
2019/01/03 Javascript
小程序:授权、登录、session_key、unionId的详解
2019/05/15 Javascript
微信小程序实现打开并下载服务器上面的pdf文件到手机
2019/09/20 Javascript
vue中的v-model原理,与组件自定义v-model详解
2020/08/04 Javascript
JavaScript实现下拉列表
2021/01/20 Javascript
python optparse模块使用实例
2015/04/09 Python
python实现定时自动备份文件到其他主机的实例代码
2018/02/23 Python
Python文本处理之按行处理大文件的方法
2018/04/09 Python
Django 路由控制的实现代码
2018/11/08 Python
pycharm运行程序时在Python console窗口中运行的方法
2018/12/03 Python
Python父目录、子目录的相互调用方法
2019/02/16 Python
python误差棒图errorbar()函数实例解析
2020/02/11 Python
python3爬虫中异步协程的用法
2020/07/10 Python
Pycharm编辑器功能之代码折叠效果的实现代码
2020/10/15 Python
CSS3中Color的一些特性介绍
2012/05/27 HTML / CSS
工程力学专业毕业生求职信
2013/10/06 职场文书
大队委员竞选稿
2015/11/20 职场文书
Redis的字符串是如何实现的
2021/10/24 Redis
通过feDisplacementMap和feImage实现水波特效
2022/04/24 HTML / CSS