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 相关文章推荐
netbeans7安装python插件的方法图解
Dec 24 Python
Python中用Decorator来简化元编程的教程
Apr 13 Python
浅析python中SQLAlchemy排序的一个坑
Feb 24 Python
对python中raw_input()和input()的用法详解
Apr 22 Python
Python设计模式之职责链模式原理与用法实例分析
Jan 11 Python
Python hashlib加密模块常用方法解析
Dec 18 Python
在PyCharm中遇到pip安装 失败问题及解决方案(pip失效时的解决方案)
Mar 10 Python
python如何求圆的面积
Jul 01 Python
Python命名空间及作用域原理实例解析
Aug 12 Python
python logging模块的使用详解
Oct 23 Python
python解包用法详解
Feb 17 Python
golang特有程序结构入门教程
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
sony ICF-2010 拆解与改装
2021/03/02 无线电
php中json_encode中文编码问题分析
2011/09/13 PHP
PHP中操作ini配置文件的方法
2013/04/25 PHP
PHP基础之运算符的使用方法
2013/04/28 PHP
PHP中使用循环实现的金字塔图形
2014/11/08 PHP
php有道翻译api调用方法实例
2014/12/22 PHP
PHP串行化与反串行化实例分析
2016/12/27 PHP
Laravel多域名下字段验证的方法
2019/04/04 PHP
jQuery 行级解析读取XML文件(附源码)
2009/10/12 Javascript
jQuery表单获取和失去焦点输入框提示效果的实例代码
2013/08/01 Javascript
下拉列表选择项的选中在不同浏览器中的兼容性问题探讨
2013/09/18 Javascript
JavaScript实现大数的运算
2014/11/24 Javascript
jQuery实现左右切换焦点图
2015/04/03 Javascript
JavaScript+html5 canvas实现本地截图教程
2020/04/16 Javascript
javascript特效实现——当前时间和倒计时效果的简单实例
2016/07/20 Javascript
BootStrap无限级分类(无限极分类封装版)
2016/08/26 Javascript
将html页面保存成图片,图片写入pdf的实现方法(推荐)
2016/09/17 Javascript
JavaScript编写一个简易购物车功能
2016/09/17 Javascript
正则表达式替换html元素属性的方法
2016/11/26 Javascript
利用jQuery插件imgAreaSelect实现图片上传裁剪(放大缩小)
2016/12/02 Javascript
JS重载实现方法分析
2016/12/16 Javascript
Mongoose实现虚拟字段查询的方法详解
2017/08/15 Javascript
详解ES6之async+await 同步/异步方案
2017/09/19 Javascript
jQuery中getJSON跨域原理的深入讲解
2020/09/02 jQuery
python实现定时播放mp3
2015/03/29 Python
详解Python中time()方法的使用的教程
2015/05/22 Python
Centos部署django服务nginx+uwsgi的方法
2019/01/02 Python
在Python 不同级目录之间模块的调用方法
2019/01/19 Python
python实现布隆过滤器及原理解析
2019/12/08 Python
在python中做正态性检验示例
2019/12/09 Python
Python3实现监控新型冠状病毒肺炎疫情的示例代码
2020/02/13 Python
Python按照list dict key进行排序过程解析
2020/04/04 Python
深入浅析python 中的self和cls的区别
2020/06/20 Python
《浅水洼里的小鱼》听课反思
2014/02/28 职场文书
通讯稿格式及范文
2015/07/22 职场文书
python字符串常规操作大全
2021/05/02 Python