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中执行shell命令的几个方法小结
Sep 18 Python
Windows下搭建python开发环境详细步骤
Jul 20 Python
基于Python 的进程管理工具supervisor使用指南
Sep 18 Python
利用python将pdf输出为txt的实例讲解
Apr 23 Python
使用python进行文本预处理和提取特征的实例
Jun 05 Python
用Python读取几十万行文本数据
Dec 24 Python
浅谈python之高阶函数和匿名函数
Mar 21 Python
解决Django 在ForeignKey中出现 non-nullable field错误的问题
Aug 06 Python
python实现网站用户名密码自动登录功能
Aug 09 Python
原生python实现knn分类算法
Oct 24 Python
python中通过pip安装库文件时出现“EnvironmentError: [WinError 5] 拒绝访问”的问题及解决方案
Aug 11 Python
Python基础详解之邮件处理
Apr 28 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/10/09 PHP
PHP学习之输出字符串(echo,print,printf,print_r和var_dump)
2011/04/17 PHP
fetchAll()与mysql_fetch_array()的区别详解
2013/06/05 PHP
php实现图片上传并进行替换操作
2016/03/15 PHP
ThinkPHP静态缓存简单配置和使用方法详解
2016/03/23 PHP
php远程下载类分享
2016/04/13 PHP
CentOS7系统搭建LAMP及更新PHP版本操作详解
2020/03/26 PHP
jquery中输入验证中一个不错的效果
2010/08/21 Javascript
JS文本获得焦点清除文本文字的示例代码
2014/01/13 Javascript
jQuery 2.0.3 源码分析之core(一)整体架构
2014/05/27 Javascript
推荐 21 款优秀的高性能 Node.js 开发框架
2014/08/18 Javascript
AngularJs中Bootstrap3 datetimepicker使用实例
2016/12/13 Javascript
详解基于vue-router的动态权限控制实现方案
2017/09/28 Javascript
详解基于Vue2.0实现的移动端弹窗(Alert, Confirm, Toast)组件
2018/08/02 Javascript
vue js秒转天数小时分钟秒的实例代码
2018/08/08 Javascript
vue项目打包部署到服务器的方法示例
2018/08/27 Javascript
node实现生成带参数的小程序二维码并保存到本地功能示例
2018/12/05 Javascript
Three.js中矩阵和向量的使用教程
2019/03/19 Javascript
Vue 实例事件简单示例
2019/09/19 Javascript
vue与django集成打包的实现方法
2019/11/11 Javascript
echarts.js 动态生成多个图表 使用vue封装组件操作
2020/07/19 Javascript
JS如何调用WebAssembly编译出来的.wasm文件
2020/11/05 Javascript
python3.6+opencv3.4实现鼠标交互查看图片像素
2018/02/26 Python
python UDP(udp)协议发送和接收的实例
2019/07/22 Python
python numpy数组中的复制知识解析
2020/02/03 Python
Python利用PyPDF2库获取PDF文件总页码实例
2020/04/03 Python
用python进行视频剪辑
2020/11/02 Python
柒牌官方商城:中国男装优秀品牌
2017/06/30 全球购物
纽约著名的服装辅料来源:M&J Trimming
2017/07/26 全球购物
材料采购员岗位职责
2013/12/17 职场文书
医院总经理职责
2013/12/26 职场文书
行政部经理助理岗位职责
2014/06/15 职场文书
个人委托书
2014/07/31 职场文书
毕业设计指导教师评语
2014/12/30 职场文书
2015年学生会部门工作总结
2015/04/21 职场文书
VUE之图片Base64编码使用ElementUI组件上传
2022/04/09 Vue.js