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抓取百度首页的方法
May 19 Python
python使用os.listdir和os.walk获得文件的路径的方法
Dec 16 Python
Python实现的在特定目录下导入模块功能分析
Feb 11 Python
Python3中编码与解码之Unicode与bytes的讲解
Feb 28 Python
django 多对多表的创建和插入代码实现
Sep 09 Python
Numpy之reshape()使用详解
Dec 26 Python
python实现拼图小游戏
Feb 22 Python
Python之Django自动实现html代码(下拉框,数据选择)
Mar 13 Python
Python 实现平台类游戏添加跳跃功能
Mar 27 Python
python 基于opencv 绘制图像轮廓
Dec 11 Python
matplotlib阶梯图的实现(step())
Mar 02 Python
教你漂亮打印Pandas DataFrames和Series
May 29 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
php 分页原理详解
2009/08/21 PHP
php程序的国际化实现方法(利用gettext)
2011/08/14 PHP
gd库图片下载类实现下载网页所有图片的php代码
2012/08/20 PHP
PHP实现导出excel数据的类库用法示例
2016/10/15 PHP
详解PHP序列化和反序列化原理
2018/01/15 PHP
tp5 sum某个字段相加得到总数的例子
2019/10/18 PHP
js中的escape及unescape函数的php实现代码
2007/09/04 Javascript
javascript 打印页面代码
2009/03/24 Javascript
javascript控制frame,iframe的src属性代码
2009/12/31 Javascript
js focus不起作用的解决方法(主要是因为dom元素是否加载完成)
2010/11/05 Javascript
jQuery find和children方法使用
2011/01/31 Javascript
基于jQuery选择器的整理集合
2013/04/26 Javascript
javascript实现鼠标拖动改变层大小的方法
2015/04/30 Javascript
jQuery使用中可能被XSS攻击的一些危险环节提醒
2016/05/24 Javascript
基于JavaScript实现鼠标箭头移动图片跟着移动
2016/08/30 Javascript
jQuery复合事件用法示例
2017/06/10 jQuery
AngularJS实现tab选项卡的方法详解
2017/07/05 Javascript
JS中Safari浏览器中的Date
2017/07/17 Javascript
微信小程序checkbox组件使用详解
2018/01/31 Javascript
layui 监听表格复选框选中值的方法
2018/08/15 Javascript
解决VUE中document.body.scrollTop为0的问题
2018/09/15 Javascript
Vue引用Swiper4插件无法重写分页器样式的解决方法
2018/09/27 Javascript
iview实现动态表单和自定义验证时间段重叠
2021/01/10 Javascript
如何在sae中设置django,让sae的工作环境跟本地python环境一致
2017/11/21 Python
python统计多维数组的行数和列数实例
2018/06/23 Python
python如何制作缩略图
2019/04/30 Python
pygame实现俄罗斯方块游戏(基础篇3)
2019/10/29 Python
利用4行Python代码监测每一行程序的运行时间和空间消耗
2020/04/22 Python
Python爬虫与反爬虫大战
2020/07/30 Python
详解如何将 Canvas 绘制过程转为视频
2021/01/25 HTML / CSS
GAZMAN官网:澳大利亚领先的男装品牌
2019/12/19 全球购物
工商管理专业职业生涯规划
2014/01/01 职场文书
美术毕业生求职信
2014/02/25 职场文书
学习党代会心得体会
2014/09/05 职场文书
安全生产先进个人事迹材料
2014/12/30 职场文书
springboot实现string转json json里面带数组
2022/06/16 Java/Android