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机器学习之贝叶斯分类
Mar 26 Python
WxPython建立批量录入框窗口
Feb 27 Python
python的依赖管理的实现
May 14 Python
详解python中docx库的安装过程
Nov 08 Python
Python print不能立即打印的解决方式
Feb 19 Python
Python流程控制常用工具详解
Feb 24 Python
Python如何使用turtle库绘制图形
Feb 26 Python
python+opencv边缘提取与各函数参数解析
Mar 09 Python
python实现Oracle查询分组的方法示例
Apr 30 Python
Python爬虫实例——scrapy框架爬取拉勾网招聘信息
Jul 14 Python
Python configparser模块封装及构造配置文件
Aug 07 Python
如何用Python 实现全连接神经网络(Multi-layer Perceptron)
Oct 15 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
如何开始收听短波广播
2021/03/01 无线电
php更新修改excel中的内容实例代码
2014/02/26 PHP
PHP面向对象程序设计之命名空间与自动加载类详解
2016/12/02 PHP
Laravel框架处理用户的请求操作详解
2019/12/20 PHP
关于js获取radio和select的属性并控制的代码
2011/05/12 Javascript
jQuery仿Excel表格编辑功能的实现代码
2013/05/01 Javascript
了不起的node.js读书笔记之例程分析
2014/12/22 Javascript
jquery append 动态添加的元素事件on 不起作用的解决方案
2015/07/30 Javascript
js中获取jsp表单中radio类型的值简单实例
2016/08/15 Javascript
JavaScript实现大图轮播效果
2017/01/11 Javascript
bootstrap中添加额外的图标实例代码
2017/02/15 Javascript
jQuery.ajax向后台传递数组问题的解决方法
2017/05/12 jQuery
vue-router路由懒加载和权限控制详解
2017/12/13 Javascript
Nginx 配置多站点vhost 的方法
2018/01/07 Javascript
微信小程序实现图片预览功能
2018/01/31 Javascript
微信小程序和百度的语音识别接口详解
2019/05/06 Javascript
openLayer4实现动态改变标注图标
2020/08/17 Javascript
Python中的Numeric包和Numarray包使用教程
2015/04/13 Python
Python 模拟购物车的实例讲解
2017/09/11 Python
Python实现自动为照片添加日期并分类的方法
2017/09/30 Python
致Python初学者 Anaconda入门使用指南完整版
2018/04/05 Python
Python简单过滤字母和数字的方法小结
2019/01/09 Python
Python异常模块traceback用法实例分析
2019/10/22 Python
Anaconda3+tensorflow2.0.0+PyCharm安装与环境搭建(图文)
2020/02/18 Python
PyQt5实现登录页面
2020/05/30 Python
HTML5视频播放插件 video.js介绍
2018/09/29 HTML / CSS
汤米巴哈马官方网站:Tommy Bahama
2017/05/13 全球购物
英国健身仓库:Bodybuilding Warehouse
2019/03/06 全球购物
一套C++笔试题面试题
2012/06/06 面试题
办加油卡单位介绍信
2014/01/09 职场文书
优秀大学生自荐信
2014/06/09 职场文书
不错的求职信范文
2014/07/20 职场文书
建筑安全责任书范本
2014/07/24 职场文书
2014年优秀班主任工作总结
2014/12/16 职场文书
高三毕业评语
2014/12/31 职场文书
python geopandas读取、创建shapefile文件的方法
2021/06/29 Python