2014-11-23 83 views
1

我想運行這個ICMP pinger應用程序(Python 2.7)。它給了我這個錯誤信息。Python中的ICMP pinger應用程序 - 錯誤:操作不允許?

回溯(最近最後調用): 線125,在 平( 「www.poly.edu」) 線120,在平 延遲= doOnePing(目標寄存器,超時) 線104,在doOnePing raise socket.error(msg) 錯誤:不允許操作

我不知道什麼是錯的。代碼有問題嗎?或者代碼是否正確,並且該功能因其他原因而不被允許?

from socket import * 
import os 
import sys 
import struct 
import time 
import select 
import binascii 
import socket 

ICMP_ECHO_REQUEST = 8 
timeRTT = [] 
packageSent =0; 
packageRev = 0; 

def checksum(str): 
    csum = 0 
    countTo = (len(str)/2) * 2 
    count = 0 
    while count < countTo: 
     thisVal = ord(str[count+1]) * 256 + ord(str[count]) 
     csum = csum + thisVal 
     csum = csum & 0xffffffffL 
     count = count + 2 
    if countTo < len(str): 
     csum = csum + ord(str[len(str) - 1]) 
     csum = csum & 0xffffffffL 
    csum = (csum >> 16) + (csum & 0xffff) 
    csum = csum + (csum >> 16) 
    answer = ~csum 
    answer = answer & 0xffff 
    answer = answer >> 8 | (answer << 8 & 0xff00) 
    return answer 

def receiveOnePing(mySocket, ID, timeout, destAddr): 
    global packageRev,timeRTT 
    timeLeft = timeout 
    while 1: 
     startedSelect = time.time() 
     whatReady = select.select([mySocket], [], [], timeLeft) 
     howLongInSelect = (time.time() - startedSelect) 
     if whatReady[0] == []: # Timeout 
      return "0: Destination Network Unreachable," 
     timeReceived = time.time() 
     recPacket, addr = mySocket.recvfrom(1024) 

    #Fill in start 
     #Fetch the ICMP header from the IP packet 
     icmpHeader = recPacket[20:28] 
     requestType, code, revChecksum, revId, revSequence = struct.unpack('bbHHh',icmpHeader) 
     if ID == revId: 
      bytesInDouble = struct.calcsize('d') 
      #struct.calcsize(fmt) Return the size of the struct (and hence of the string) corresponding to the given format. 
     #struct.unpack(fmt, buffer[, offset=0]) Unpack the buffer according to the given format. The result is a tuple even if it contains exactly one item. The buffer must contain at least the amount of data required by the format (len(buffer[offset:]) must be at least calcsize(fmt)). 
      timeData = struct.unpack('d',recPacket[28:28 + bytesInDouble])[0] 
      timeRTT.append(timeReceived - timeData) 
      packageRev += 1 
      return timeReceived - timeData 
     else: 
      return "ID does not match" 
     #Fill in end 

     timeLeft = timeLeft - howLongInSelect 
     if timeLeft <= 0: 
      return "1: Request timed out." 

def sendOnePing(mySocket, destAddr, ID): 
    global packageSent 
    # Header is type (8), code (8), checksum (16), id (16), sequence (16) 

    myChecksum = 0 
    # Make a dummy header with a 0 checksum. 
    # struct -- Interpret strings as packed binary data 
    header = struct.pack("bbHHh", ICMP_ECHO_REQUEST, 0, myChecksum, ID, 1) 
    data = struct.pack("d", time.time()) 
    # Calculate the checksum on the data and the dummy header. 
    myChecksum = checksum(header + data) 

    # Get the right checksum, and put in the header 
    if sys.platform == 'darwin': 
     myChecksum = socket.htons(myChecksum) & 0xffff 
     #Convert 16-bit integers from host to network byte order. 
    else: 
     myChecksum = socket.htons(myChecksum) 

    header = struct.pack("bbHHh", ICMP_ECHO_REQUEST, 0, myChecksum, ID, 1) 
    packet = header + data 

    mySocket.sendto(packet, (destAddr, 1)) 
    packageSent += 1 
    # AF_INET address must be tuple, not str 
    #Both LISTS and TUPLES consist of a number of objects 
    #which can be referenced by their position number within the object 

def doOnePing(destAddr, timeout): 
    icmp = socket.getprotobyname("icmp") 
    #SOCK_RAW is a powerful socket type. For more details see:http://sock-raw.org/papers/sock_raw 

    #Fill in start 
    #Create Socket here 
    try: 
     mySocket = socket.socket(socket.AF_INET, socket.SOCK_RAW, icmp) 
    except socket.error, (errno, msg): 
     if errno == 1: 
      raise socket.error(msg) 
    #Fill in end 

    myID = os.getpid() & 0xFFFF #Return the current process i 
    sendOnePing(mySocket, destAddr, myID) 
    delay = receiveOnePing(mySocket, myID, timeout, destAddr) 
    mySocket.close() 
    return delay 

def ping(host, timeout=1): 
    #timeout=1 means: If one second goes by without a reply from the server, 
    dest = socket.gethostbyname(host) 
    print "Pinging " + dest + " using Python:" 
    print "" 
    #Send ping requests to a server separated by approximately one second 
    while 1 : 
     delay = doOnePing(dest, timeout) 
     print "RTT:",delay 
     time.sleep(1)# one second 
    return delay 

ping("www.poly.edu") 

回答

1

要使用raw_sockets Python需要以root身份運行。如果你通過sudo運行腳本(假設Linux/UNIX),那麼它應該可以工作。如果使用Windows,請以管理員身份運行Python。

值得一提的是,當我在CentOS 6.5虛擬機上以root身份運行代碼時,您的代碼對我來說工作得很好。

+0

謝謝,我有一種感覺,代碼是好的。我會放過它,我不想繞過任何安全措施。 – 2014-11-23 22:02:50

+0

不客氣..請確保接受我的答案,如果它解決了問題:) – mdadm 2014-11-24 03:35:55

相關問題