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 相关文章推荐
Python3基础之条件与循环控制实例解析
Aug 13 Python
Python实现方便使用的级联进度信息实例
May 05 Python
Python发送form-data请求及拼接form-data内容的方法
Mar 05 Python
python UNIX_TIMESTAMP时间处理方法分析
Apr 18 Python
一个基于flask的web应用诞生 组织结构调整(7)
Apr 11 Python
Python3结合Dlib实现人脸识别和剪切
Jan 24 Python
python实现图书馆研习室自动预约功能
Apr 27 Python
浅谈python连续赋值可能引发的错误
Nov 10 Python
Python定时任务APScheduler的实例实例详解
Jul 22 Python
结合OpenCV与TensorFlow进行人脸识别的实现
Oct 10 Python
将pycharm配置为matlab或者spyder的用法说明
Jun 08 Python
Django websocket原理及功能实现代码
Nov 14 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面向对象编程快速入门
2006/12/14 PHP
PHP中uploaded_files函数使用方法详解
2011/03/09 PHP
数组任意位置插入元素,删除特定元素的实例
2017/03/02 PHP
PHP实现的猴王算法(猴子选大王)示例
2018/04/30 PHP
PHP7原生MySQL数据库操作实现代码
2020/07/03 PHP
js中 关于undefined和null的区别介绍
2013/04/16 Javascript
jQuery实现的可编辑表格完整实例
2016/06/20 Javascript
浅谈$('div a') 与$('div&gt;a')的区别
2016/07/18 Javascript
js实现随机点名系统(实例讲解)
2017/10/18 Javascript
JS使用tofixed与round处理数据四舍五入的区别
2017/10/25 Javascript
解决option标签selected=&quot;selected&quot;属性失效的问题
2017/11/06 Javascript
react在安卓中输入框被手机键盘遮挡问题的解决方法
2018/09/03 Javascript
vue 音乐App QQ音乐搜索列表最新接口跨域设置方法
2018/09/25 Javascript
JS跨域请求的问题解析
2018/12/03 Javascript
js实现简易ATM功能
2020/10/27 Javascript
[01:33:14]LGD vs VP Supermajor 败者组决赛 BO3 第二场 6.10
2018/07/04 DOTA
老生常谈Python基础之字符编码
2017/06/14 Python
python os模块简单应用示例
2019/05/23 Python
10 行Python 代码实现 AI 目标检测技术【推荐】
2019/06/14 Python
python的pygal模块绘制反正切函数图像方法
2019/07/16 Python
pycharm重命名文件的方法步骤
2019/07/29 Python
使用keras内置的模型进行图片预测实例
2020/06/17 Python
一款纯css3实现的tab选项卡的实列教程
2014/12/11 HTML / CSS
美国指甲油品牌:Deco Miami
2017/01/30 全球购物
顺丰快递Java软件工程师面试题
2015/07/31 面试题
自荐信格式范文
2013/10/07 职场文书
创业计划书中要认真思考的问题
2013/12/28 职场文书
社区服务活动总结
2014/05/07 职场文书
员工试用期自我评价
2014/09/18 职场文书
领导班子专题民主生活会情况想汇报
2014/09/30 职场文书
征求意见函
2015/06/05 职场文书
入党宣誓仪式主持词
2015/06/29 职场文书
信息技术国培研修日志
2015/11/13 职场文书
2016年度基层党建工作公开承诺书
2016/03/25 职场文书
JavaWeb 入门篇(3)ServletContext 详解 具体应用
2021/07/16 Java/Android
Android实现图片九宫格
2022/06/28 Java/Android