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 可爱的大小写
Sep 06 Python
Python smtplib实现发送邮件功能
May 22 Python
Python简单实现网页内容抓取功能示例
Jun 07 Python
Python实例方法、类方法、静态方法的区别与作用详解
Mar 25 Python
Python3.5面向对象编程图文与实例详解
Apr 24 Python
pymysql模块的操作实例
Dec 17 Python
python关于调用函数外的变量实例
Dec 26 Python
Python中bisect的使用方法
Dec 31 Python
使用keras实现孪生网络中的权值共享教程
Jun 11 Python
vscode+PyQt5安装详解步骤
Aug 12 Python
Django CBV模型源码运行流程详解
Aug 17 Python
基于Python制作一副扑克牌过程详解
Oct 19 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程序员的技术瓶颈分析
2011/07/17 PHP
WordPress中重置文章循环的rewind_posts()函数讲解
2016/01/11 PHP
PHP模拟post提交数据方法汇总
2016/02/16 PHP
分享几种好用的PHP自定义加密函数(可逆/不可逆)
2020/09/15 PHP
许愿墙中用到的函数
2006/10/07 Javascript
一份老外写的XMLHttpRequest代码多浏览器支持兼容性
2007/01/11 Javascript
jQueryUI写一个调整分类的拖放效果实现代码
2012/05/10 Javascript
JavaScript高级程序设计 阅读笔记(二十一) JavaScript中的XML
2012/09/14 Javascript
javascript数组快速打乱重排的方法
2014/01/02 Javascript
控制文字内容的显示与隐藏示例
2014/06/11 Javascript
简介JavaScript中的unshift()方法的使用
2015/06/09 Javascript
基于javascript如何传递特殊字符
2015/11/30 Javascript
JS 实现导航菜单中的二级下拉菜单的几种方式
2016/10/31 Javascript
原生js实现仿window10系统日历效果的实例
2017/10/31 Javascript
Node.js操作系统OS模块用法分析
2019/01/04 Javascript
微信小程序页面间传值与页面取值操作实例分析
2019/04/30 Javascript
javascript简单实现深浅拷贝过程详解
2019/10/08 Javascript
Python用于学习重要算法的模块pygorithm实例浅析
2018/08/16 Python
python检测IP地址变化并触发事件
2018/12/26 Python
python 批量解压压缩文件的实例代码
2019/06/27 Python
Pytorch卷积层手动初始化权值的实例
2019/08/17 Python
python函数声明和调用定义及原理详解
2019/12/02 Python
使用Python第三方库pygame写个贪吃蛇小游戏
2020/03/06 Python
学python爬虫能做什么
2020/07/29 Python
解决python和pycharm安装gmpy2 出现ERROR的问题
2020/08/28 Python
JBL英国官网:JBL UK
2018/07/04 全球购物
美国批发供应商:Kole Imports
2019/04/10 全球购物
世界上最受欢迎的钓鱼诱饵:Rapala
2019/05/02 全球购物
SQL Server提供的3种恢复模型都是什么? 有什么区别?
2012/05/13 面试题
开工庆典邀请函范文
2014/01/16 职场文书
劳动者解除劳动合同通知书
2015/04/16 职场文书
诚信考试承诺书范文
2015/04/29 职场文书
介绍信怎么写
2015/05/05 职场文书
党支部审查意见
2015/06/02 职场文书
提取视频中的音频 Python只需要三行代码!
2021/05/10 Python
vue.js Router中嵌套路由的实用示例
2021/06/27 Vue.js