700字范文,内容丰富有趣,生活中的好帮手!
700字范文 > 使用python 实现icmp测试主机存活性

使用python 实现icmp测试主机存活性

时间:2020-11-25 04:38:42

相关推荐

使用python 实现icmp测试主机存活性

代码:

#!/usr/bin/env python#coding:utf-8importos, sys, socket, struct, select, time# From /usr/include/linux/icmp.h; your milage may vary.ICMP_ECHO_REQUEST=8# Seems to be the same on Solaris.defchecksum(source_string):"""I'm not too confident that this is right but testing seemsto suggest that it gives the same answers as in_cksum in ping.c"""sum=0countTo=(len(source_string)/2)*2count=0whilecount<countTo:thisVal=ord(source_string[count+1])*256+ord(source_string[count])sum=sum+thisValsum=sum&0xffffffff# Necessary?count=count+2ifcountTo<len(source_string):sum=sum+ord(source_string[len(source_string)-1])sum=sum&0xffffffff# Necessary?sum=(sum>>16)+(sum&0xffff)sum=sum+(sum>>16)answer=~sumanswer=answer &0xffff# Swap bytes. Bugger me if I know why.answer=answer >>8| (answer <<8&0xff00)returnanswerdefreceive_one_ping(my_socket,ID, timeout):"""receive the ping from the socket."""timeLeft=timeoutwhileTrue:startedSelect=time.time()whatReady=select.select([my_socket], [], [], timeLeft)howLongInSelect=(time.time()-startedSelect)ifwhatReady[0]==[]:# TimeoutreturntimeReceived=time.time()recPacket, addr=my_socket.recvfrom(1024)icmpHeader=recPacket[20:28]type, code, checksum, packetID, sequence=struct.unpack("bbHHh", icmpHeader)ifpacketID==ID:bytesInDouble=struct.calcsize("d")timeSent=struct.unpack("d", recPacket[28:28+bytesInDouble])[0]returntimeReceived-timeSenttimeLeft=timeLeft-howLongInSelectiftimeLeft <=0:returndefsend_one_ping(my_socket, dest_addr,ID):"""Send one ping to the given >dest_addr<."""dest_addr=socket.gethostbyname(dest_addr)# Header is type (8), code (8), checksum (16), id (16), sequence (16)my_checksum=0# Make a dummy heder with a 0 checksum.header=struct.pack("bbHHh", ICMP_ECHO_REQUEST,0, my_checksum,ID,1)#压包#a1 = struct.unpack("bbHHh",header) #my testbytesInDouble=struct.calcsize("d")data=(192-bytesInDouble)*"Q"data=struct.pack("d", time.time())+data# Calculate the checksum on the data and the dummy header.my_checksum=checksum(header+data)# Now that we have the right checksum, we put that in. It's just easier# to make up a new header than to stuff it into the dummy.header=struct.pack("bbHHh", ICMP_ECHO_REQUEST,0, socket.htons(my_checksum),ID,1)packet=header+datamy_socket.sendto(packet, (dest_addr,1))# Don't know about the 1defdo_one(dest_addr, timeout):"""Returns either the delay (in seconds) or none on timeout."""icmp=socket.getprotobyname("icmp")try:my_socket=socket.socket(socket.AF_INET, socket.SOCK_RAW, icmp)exceptsocket.error, (errno, msg):iferrno==1:# Operation not permittedmsg=msg+(" - Note that ICMP messages can only be sent from processes"" running as root.")raisesocket.error(msg)raise# raise the original errormy_ID=os.getpid() &0xFFFFsend_one_ping(my_socket, dest_addr, my_ID)delay=receive_one_ping(my_socket, my_ID, timeout)my_socket.close()returndelaydefverbose_ping(dest_addr, timeout=2, count=100):"""Send >count< ping to >dest_addr< with the given >timeout< and displaythe result."""foriinxrange(count):print"ping %s..."%dest_addr,try:delay=do_one(dest_addr, timeout)exceptsocket.gaierror, e:print"failed. (socket error: '%s')"%e[1]breakifdelay==None:print"failed. (timeout within %ssec.)"%timeoutelse:delay=delay*1000print"get ping in %0.4fms"%delayif__name__=='__main__':

verbose_ping("",2,1)

用到的模块解析:

struct:

最近在学习python网络编程这一块,在写简单的socket通信代码时,遇到了struct这个模块的使用,当时不太清楚这到底有和作用,后来查阅了相关资料大概了解了,在这里做一下简单的总结。

了解c语言的人,一定会知道struct结构体在c语言中的作用,它定义了一种结构,里面包含不同类型的数据(int,char,bool等等),方便对某一结构对象进行处理。而在网络通信当中,大多传递的数据是以二进制流(binary data)存在的。当传递字符串时,不必担心太多的问题,而当传递诸如int、char之类的基本数据的时候,就需要有一种机制将某些特定的结构体类型打包成二进制流的字符串然后再网络传输,而接收端也应该可以通过某种机制进行解包还原出原始的结构体数据。python中的struct模块就提供了这样的机制,该模块的主要作用就是对python基本类型值与用python字符串格式表示的C struct类型间的转化(This module performs conversions between Python values and C structs represented as Python strings.)。stuct模块提供了很简单的几个函数,下面写几个例子。

struct提供用format specifier方式对数据进行打包和解包(Packing and Unpacking)。例如:

输出:

Original values: (1, 'abc', 2.7)

Format string : I3sf

Uses : 12 bytes

Packed Value : 0100000061626300cdcc2c40

Unpacked Type : <type 'tuple'> Value: (1, 'abc', 2.700000047683716)

代码中,首先定义了一个元组数据,包含int、string、float三种数据类型,然后定义了struct对象,并制定了format‘I3sf’,I 表示int,3s表示三个字符长度的字符串,f 表示 float。最后通过struct的pack和unpack进行打包和解包。通过输出结果可以发现,value被pack之后,转化为了一段二进制字节串,而unpack可以把该字节串再转换回一个元组,但是值得注意的是对于float的精度发生了改变,这是由一些比如操作系统等客观因素所决定的。打包之后的数据所占用的字节数与C语言中的struct十分相似。

select 模块:

Python中的select模块专注于I/O多路复用,提供了select poll epoll三个方法(其中后两个在Linux中可用,windows仅支持select),另外也提供了kqueue方法(freeBSD系统)

select方法:

进程指定内核监听哪些文件描述符(最多监听1024个fd)的哪些事件,当没有文件描述符事件发生时,进程被阻塞;当一个或者多个文件描述符事件发生时,进程被唤醒。

当我们调用select()时:

1 上下文切换转换为内核态

2 将fd从用户空间复制到内核空间

3 内核遍历所有fd,查看其对应事件是否发生

4 如果没发生,将进程阻塞,当设备驱动产生中断或者timeout时间后,将进程唤醒,再次进行遍历

5 返回遍历后的fd

6 将fd从内核空间复制到用户空间

fd:file descriptor 文件描述符

fd_r_list,fd_w_list,fd_e_list=.秒,之后返回三个空列表,如果监听的句柄有变化,则直接执行。

本内容不代表本网观点和政治立场,如有侵犯你的权益请联系我们处理。
网友评论
网友评论仅供其表达个人看法,并不表明网站立场。