[Errno 56]: 如何修复已连接的套接字?
我正在做一个 ICMP ping 程序,但遇到了问题。当我在终端运行程序时,首先输入了 sudo su
,这样我就有了管理员权限,因为我们需要使用原始套接字。然后,当我运行程序时,出现了这个错误信息:
sh-3.2# python3 icmp.py
Pinging 31.13.66.112 using Python:
Traceback (most recent call last):
File "icmp.py", line 149, in <module>
ping("www.facebook.com")
File "icmp.py", line 141, in ping
delay = doOnePing(dest,timeout)
File "icmp.py", line 123, in doOnePing
sendOnePing(mySocket,destAddr,myID)
File "icmp.py", line 111, in sendOnePing
mySocket.sendto(packet,(destAddr,1))
OSError: [Errno 56] Socket is already connected
这是我正在运行的代码:
import os
from socket import *
from sys import *
from struct import *
from time import *
from select import *
from binascii import *
ICMP_ECHO_REQUEST = 8
def checksum (val):
csum = 0
countTo = (len(val) // 2) * 2
count = 0
while count < countTo:
thisVal = val[count+1] * 256 + val[count]
csum = csum + thisVal
csum = csum & 0xffffffff
count = count + 2
if countTo < len(val):
csum = csum + val[len(val) - 1]
csum = csum & 0xffffffff
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()
whatReady = select([mySocket],[],[],timeLeft)
howLongInSelect = (time() - startedSelect)
if whatReady[0] == []: #Timeout
return "Request timed out."
timeReceived = time()
recPacket, addr = mySocket.recvfrom(1024)
icmpHeader = recPacket[20:28]
kind,code,checksum,idNum,sequence = unpack("bbHHh",icmpHeader)
if idNum == ID:
sizeofdouble = calcsize("d")
timeSent = unpack("d",recPacket[28:28+sizeofdouble])[0]
print(("TYPE: %d CODE: %d CHECKSUM: 0x%08x ID: %d SEQ: %d TIME: %d ms\n" % (kind,code,checksum,idNum,sequence,timeReceived - timeSent)*1000))
timeLeft = timeLeft - howLongInSelect
if timeLeft <= 0:
return "Request timed out."
else:
return "Reply from %s successfully." % destAddr
def sendOnePing(mySocket, destAddr, ID):
myChecksum = 0
header = pack("bbHHh", ICMP_ECHO_REQUEST, 0, myChecksum, ID, 1)
data = pack("d",time())
myChecksum = checksum(header + data)
if platform == 'darwin':
myChecksum = htons(myChecksum) & 0xffff
else:
myChecksum = htons(myChecksum)
header = pack("bbHHh", ICMP_ECHO_REQUEST,0,myChecksum,ID,1)
packet = header + data
mySocket.sendto(packet,(destAddr,1))
def doOnePing(destAddr,timeout):
icmp = getprotobyname("icmp")
mySocket = socket(AF_INET,SOCK_RAW,icmp)
mySocket.connect((destAddr,80))
myID = os.getpid() & 0xFFFF
sendOnePing(mySocket,destAddr,myID)
delay = receiveOnePing(mySocket,myID,timeout,destAddr)
mySocket.close()
return delay
def ping(host,timeout = 1):
dest = gethostbyname(host)
print("Pinging " + dest + " using Python:")
print()
while 1:
delay = doOnePing(dest,timeout)
print(delay)
sleep(1)
return delay
ping("www.facebook.com")
我们得到了一个实验指导,上面有“骨架”程序的框架,我们需要填补缺失的部分。这是提供骨架代码的实验指导
注意:由于我为了修复之前出现的其他错误而不得不更改一些内容,所以骨架代码和我的程序不会完全匹配。
谢谢大家的帮助,
Tyler
2 个回答
1
你应该用“bind”,而不是“connect”。然后这个程序你需要以管理员身份运行,比如在Linux或Mac OS上用“sudo python3 icmp.py”来执行。希望这能帮到你。谢谢!
1
首先,你需要connect
这个套接字,也就是告诉它要把数据发送到哪个地址。然后再调用sendto
,这时候你又要提供一次对方的地址。即使这两个地址是一样的,套接字也会搞混。
所以,要么就不要connect
,要么直接使用send
。