1
votes

Still figuring out this python stuff. I have been messing around with a pinger protocol. It is not completed yet quite as I want, but it is on it's way.

mySocket = socket.socket(socket.AF_INET, socket.SOCK_STREAM, icmp) AttributeError: type object '_socketobject' has no attribute 'socket'

This is the error I am getting, and the problems seem to exist totally in "doOnePing". I will also add the complete code below this incase anyone was wondering what was going on everywhere else. I am using

from socket import *

Thank you for your help.

def doOnePing(destAddr, timeout):

    icmp = getprotobyname("icmp")

    try:
        mySocket = socket(AF_INET, SOCK_STREAM, icmp)
    except error, (errno,msg):
        if errno == 1:
            msg = msg +(" - ICMP messages can only be sent when running as root")
            raise error(msg)
        raise

    myID = os.getpid() & 0xFFFF  # Return the current process i

    sendOnePing(mySocket, destAddr, myID)
    delay = receiveOnePing(mySocket, myID, timeout, destAddr)

    mySocket.close()
    return delay

Complete Code

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

ICMP_ECHO_REQUEST = 8


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):
    timeLeft = timeout

    while 1:
        startedSelect = time.time()
        whatReady = select.select([mySocket], [], [], timeLeft)
        howLongInSelect = (time.time() - startedSelect)
        if whatReady[0] == []:  # Timeout
            return "Request timed out."

        timeReceived = time.time()
        recPacket, addr = mySocket.recvfrom(1024)

        # Fill in start
        icmpHeader = recPacket[20:28]
        type, code, checksum, packetID, sequence = struct.unpack("bbHHh", icmpHeader)

        if packetID == ID:
                bytesInDouble = struct.calcsize("d")
                timeSent = struct.unpack("d", recPacket[28:28 + bytesInDouble])[0]
                return timeReceived-timeSent

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


def sendOnePing(mySocket, destAddr, ID):
    # 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':
        # Convert 16-bit integers from host to network  byte order
        myChecksum = htons(myChecksum) & 0xffff
    else:
        myChecksum = htons(myChecksum)

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

    mySocket.sendto(packet, (destAddr, 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 = getprotobyname("icmp")

    try:
        mySocket = socket(AF_INET, SOCK_STREAM, icmp)
    except error, (errno,msg):
        if errno == 1:
            msg = msg +(" - ICMP messages can only be sent when running as root")
            raise error(msg)
        raise

    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,
    # the client assumes that either the client's ping or the server's pong is lost
    dest = gethostbyname(host)
    print "Pinging " + dest + " using Python:"
    print ""

# Fill in start

    count = 100
    for i in xrange(count):
        delay = doOnePing(host, timeout)

        if delay == None:
            print "failed. (timeout within %ssec.)" % timeout
        else:
            delay = delay * 1000
            print "get ping in %0.4fms" % delay
    print

# Send 100 ping requests to a server separated by approximately one second.
# Report the minimum, maximum, and average RTTs at the end of all pings from the client.
# In addition, calculate the packet loss rate (in percentage).



ping("google.com")

UPDATE: Thank for the help. I removed the socket. when I created my socket, now I am getting the error

_sock = _realsocket(family, type, proto)

socket.error: [Errno 41] Protocol wrong type for socket

2
The documentation docs.python.org/2/library/socket.html#socket.getprotobyname suggests you only need to be using socket.getprotobyname if you're using socket.SOCK_RAW instead of socket.SOCK_STREAM. I'd try stripping out the getprotobyname business, and if that doesn't work, changing SOCK_STEAM to SOCK_RAW.jwilner

2 Answers

1
votes

Change from from socket import * to import socket

When you do from socket import *, socket.socket will shadow the package with the same package named socket. It's in general better to be specific about what you are importing.

0
votes

You've imported the class socket into your namespace without the module prefix, but you're trying to access it with the module prefix when you do socket.socket in doOnePing.

For the record, you should be skeptical about from <module> import * imports, because when you use them you're no longer explicit about what's in your namespace.