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中的私有属性
Aug 21 Python
Python中的探索性数据分析(功能式)
Dec 22 Python
python中实现数组和列表读取一列的方法
Apr 03 Python
Python变量赋值的秘密分享
Apr 03 Python
Django如何配置mysql数据库
May 04 Python
python+selenium实现自动抢票功能实例代码
Nov 23 Python
python3实现多线程聊天室
Dec 12 Python
Python3常用内置方法代码实例
Nov 18 Python
利用pandas将非数值数据转换成数值的方式
Dec 18 Python
python如何调用java类
Jul 05 Python
python接入支付宝的实例操作
Jul 20 Python
Python3 类型标注支持操作
Jun 02 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
dede3.1分页文字采集过滤规则详说(图文教程)
2007/04/03 PHP
解析smarty模板中类似for的功能实现
2013/06/18 PHP
JavaScript prototype属性深入介绍
2012/11/27 Javascript
JS控制按钮10秒钟后可用的方法
2015/12/22 Javascript
关于Vue.js一些问题和思考学习笔记(2)
2016/12/02 Javascript
JS实现复制内容到剪贴板功能
2017/02/05 Javascript
详解nodejs中express搭建权限管理系统
2017/09/15 NodeJs
从setTimeout看js函数执行过程
2017/12/19 Javascript
解决webpack+Vue引入iView找不到字体文件的问题
2018/09/28 Javascript
Node.js的进程管理的深入理解
2019/01/09 Javascript
TypeScript魔法堂之枚举的超实用手册
2020/10/29 Javascript
[04:28]2014DOTA2国际邀请赛 采访小兔子LGD挺进钥匙体育馆
2014/07/14 DOTA
Python实现优先级队列结构的方法详解
2016/06/02 Python
Python模拟登陆实现代码
2017/06/14 Python
java中两个byte数组实现合并的示例
2018/05/09 Python
python批量从es取数据的方法(文档数超过10000)
2018/12/27 Python
Python设计模式之职责链模式原理与用法实例分析
2019/01/11 Python
Python中查看变量的类型内存地址所占字节的大小
2019/06/26 Python
python使用百度文字识别功能方法详解
2019/07/23 Python
Pycharm自带Git实现版本管理的方法步骤
2020/09/18 Python
使用Canvas操作像素的方法
2018/06/14 HTML / CSS
html5+svg学习指南之SVG基础知识
2014/12/17 HTML / CSS
公务员的自我鉴定
2013/10/26 职场文书
夏季奶茶店创业计划书
2014/01/16 职场文书
计算机专业职业生涯规划范文
2014/01/19 职场文书
城管综合整治方案
2014/05/01 职场文书
无传销社区工作方案
2014/05/13 职场文书
经管应届生求职信范文
2014/05/18 职场文书
小学生我的梦想演讲稿
2014/08/21 职场文书
群众路线查摆问题整改措施思想汇报
2014/10/10 职场文书
高三英语复习计划
2015/01/19 职场文书
房产遗嘱范本
2015/08/06 职场文书
mysql获取指定时间段中所有日期或月份的语句(不设存储过程,不加表)
2021/06/18 MySQL
Python Pandas pandas.read_sql函数实例用法
2021/06/21 Python
Python多个MP4合成视频的实现方法
2021/07/16 Python
面试被问select......for update会锁表还是锁行
2021/11/11 MySQL