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中optionParser模块的使用方法实例教程
Aug 29 Python
在Python中使用pngquant压缩png图片的教程
Apr 09 Python
Python生成短uuid的方法实例详解
May 29 Python
django admin 后台实现三级联动的示例代码
Jun 22 Python
python得到qq句柄,并显示在前台的方法
Oct 14 Python
python 定时任务去检测服务器端口是否通的实例
Jan 26 Python
详解Python3中ceil()函数用法
Feb 19 Python
python实现文件的备份流程详解
Jun 18 Python
Python Numpy库常见用法入门教程
Jan 16 Python
pycharm的python_stubs问题
Apr 08 Python
Python使用pdb调试代码的技巧
May 03 Python
解决运行出现'dict' object has no attribute 'has_key'问题
Jul 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
在PHP中使用模板的方法
2008/05/24 PHP
php魔术变量用法实例详解
2014/11/13 PHP
基于php伪静态的实现方法解析
2020/07/31 PHP
javaScript 读取和设置文档元素的样式属性
2009/04/14 Javascript
js setattribute批量设置css样式
2009/11/26 Javascript
JavaScript 放大镜 移动镜片效果代码
2011/05/09 Javascript
jquery判断浏览器类型的代码
2012/11/05 Javascript
JavaScript(js)设置默认输入焦点(focus)
2012/12/28 Javascript
JavaScript在IE和FF下的兼容性问题
2014/05/19 Javascript
jQuery实现页面滚动时动态加载内容的方法
2015/03/20 Javascript
jquery实现动态改变div宽度和高度
2015/05/08 Javascript
详解AngularJS中自定义指令的使用
2015/06/17 Javascript
教你如何终止JQUERY的$.AJAX请求
2016/02/23 Javascript
Bootstrap Table表格一直加载(load)不了数据的快速解决方法
2016/09/17 Javascript
JavaScript中Math对象的方法介绍
2017/01/05 Javascript
jQuery弹出窗口简单实现代码
2017/03/09 Javascript
在iframe中使bootstrap的模态框在父页面弹出问题
2017/08/07 Javascript
解决vue-cli + webpack 新建项目出错的问题
2018/03/20 Javascript
JavaScript中的null和undefined用法解析
2019/09/30 Javascript
Python操作Mysql实例代码教程在线版(查询手册)
2013/02/18 Python
200行自定义python异步非阻塞Web框架
2017/03/15 Python
Python递归实现汉诺塔算法示例
2018/03/19 Python
Pycharm 实现下一个文件引用另外一个文件的方法
2019/01/17 Python
配置python的编程环境之Anaconda + VSCode的教程
2020/03/29 Python
python不到50行代码完成了多张excel合并的实现示例
2020/05/28 Python
python编写softmax函数、交叉熵函数实例
2020/06/11 Python
突袭HTML5之Javascript API扩展4—拖拽(Drag/Drop)概述
2013/01/31 HTML / CSS
泰国综合购物网站:Lazada泰国
2018/04/09 全球购物
GoDaddy英国:全球排名第一的域名注册商
2018/06/08 全球购物
乐高瑞士官方商店:LEGO CH
2020/08/16 全球购物
最美护士演讲稿
2014/08/27 职场文书
2015年安全生产责任书
2015/01/30 职场文书
张丽莉观后感
2015/06/16 职场文书
pytorch--之halfTensor的使用详解
2021/05/24 Python
详解Java ES多节点任务的高效分发与收集实现
2021/06/30 Java/Android
ubuntu端向日葵键盘输入卡顿问题及解决
2022/12/24 Servers