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通过邮件服务器端口发送邮件的方法
Apr 30 Python
PyCharm 常用快捷键和设置方法
Dec 20 Python
python matplotlib 注释文本箭头简单代码示例
Jan 08 Python
python编程嵌套函数实例代码
Feb 11 Python
python验证码识别教程之利用投影法、连通域法分割图片
Jun 04 Python
Flask框架URL管理操作示例【基于@app.route】
Jul 23 Python
Python的UTC时间转换讲解
Feb 26 Python
python格式化输出保留2位小数的实现方法
Jul 02 Python
django基于存储在前端的token用户认证解析
Aug 06 Python
PIL.Image.open和cv2.imread的比较与相互转换的方法
Jun 03 Python
Keras搭建自编码器操作
Jul 03 Python
一文读懂python Scrapy爬虫框架
Feb 24 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
YB217、YB235、YB400浅听
2021/03/02 无线电
php将图片保存为不同尺寸图片的图片类实例
2015/03/30 PHP
php二维码生成以及下载实现
2017/09/28 PHP
php微信开发之谷歌测距
2018/06/14 PHP
PHP实现提高SESSION响应速度的几种方法详解
2019/08/09 PHP
关于实现代码语法标亮 dp.SyntaxHighlighter
2007/02/02 Javascript
jQuery 性能优化指南 (1)
2009/05/21 Javascript
浅析JQuery获取和设置Select选项的常用方法总结
2013/07/04 Javascript
jquery获取div距离窗口和父级dv的距离示例
2013/10/10 Javascript
js简单实现交换Li的值
2014/05/22 Javascript
详解JavaScript基于面向对象之继承
2015/12/13 Javascript
AngularJs 60分钟入门基础教程
2016/04/03 Javascript
JS实现控制文本框的内容
2016/07/10 Javascript
javascript实现根据汉字获取简拼
2016/09/25 Javascript
详细AngularJs4的图片剪裁组件的实例
2017/07/12 Javascript
vue.js中引入vuex储存接口数据及调用的详细流程
2017/12/14 Javascript
详解js中let与var声明变量的区别
2020/04/05 Javascript
基于Vue实现电商SKU组合算法问题
2019/05/29 Javascript
浅谈layui使用模板引擎动态渲染元素要注意的问题
2019/09/14 Javascript
react-native聊天室|RN版聊天App仿微信实例|RN仿微信界面
2019/11/12 Javascript
python使用pymysql实现操作mysql
2016/09/13 Python
Python解惑之整数比较详解
2017/04/24 Python
使用Python写一个贪吃蛇游戏实例代码
2017/08/21 Python
python获取多线程及子线程的返回值
2017/11/15 Python
使用Python监控文件内容变化代码实例
2018/06/04 Python
wtfPython—Python中一组有趣微妙的代码【收藏】
2018/08/31 Python
使用python获取电脑的磁盘信息方法
2018/11/01 Python
Python3.7 读取 mp3 音频文件生成波形图效果
2019/11/05 Python
使用OpenCV circle函数图像上画圆的示例代码
2019/12/27 Python
在脚本中单独使用django的ORM模型详解
2020/04/01 Python
Perfume’s Club美国官网:西班牙第一家在线美容店
2020/06/10 全球购物
优秀的应届生自荐信
2014/05/23 职场文书
阿甘正传观后感
2015/06/01 职场文书
解决Goland 同一个package中函数互相调用的问题
2021/05/06 Golang
Python进行区间取值案例讲解
2021/08/02 Python
Win10/Win11 任务栏替换成经典样式
2022/04/19 数码科技