我正在尝试在 python 中实现多 ping 代码,但问题是在下面的代码中,我定义的两个套接字似乎都从 SAME DESTINATION 接收了 SAME PACKET!为什么会这样?哦
- - - - - - - - - - 更新 - - - - - - - - - -
我注意到接收到的数据包始终是“最快”的数据包[即具有较小 RTT 的数据包]!例如:
dests_list = ['173.194.41.70','213.92.16.101'] -> DEST: 173.194.41.70
dests_list = ['213.92.16.101','173.194.41.70'] -> DEST: 173.194.41.70
dests_list = ['213.92.16.191','95.141.47.7'] -> DEST: 213.92.16.191
和:
RTT_213.92.16.191=20ms RTT_173.194.41.70=8ms RTT_95.141.47.7=28ms
- - - - - - - - - - 更新 - - - - - - - - - -
代码 --> [在帖子的末尾有一个可下载的版本以避免格式问题]
#!/usr/bin/python
# -*- coding: utf-8 -*-
from exceptions import Exception
import random
import select
import socket
import struct
import sys
import time
ICMP_ECHO_REQUEST = 8 # Seems to be the same on Solaris.
PACKET_SIZE = 32
IS_WIN = False
my_socket_list = []
dests_list = ['173.194.41.70','213.92.16.101']
N_DESTS = 2
seq_num = 1
#----------------------------------------------------------------------------------------#
#----> CHECKSUM: calculate checksum
#----------------------------------------------------------------------------------------#
def checksum(source_string):
"""
I'm not too confident that this is right but testing seems
to suggest that it gives the same answers as in_cksum in ping.c
"""
sum = 0
countTo = len(source_string) / 2 * 2
count = 0
while count < countTo:
thisVal = ord(source_string[count + 1]) * 256 + ord(source_string[count])
sum = sum + thisVal
sum = sum & 0xffffffff # Necessary?
count = count + 2
if countTo < len(source_string):
sum = sum + ord(source_string[len(source_string) - 1])
sum = sum & 0xffffffff # Necessary?
sum = (sum >> 16) + (sum & 65535)
sum = sum + (sum >> 16)
answer = ~sum
answer = answer & 65535
# Swap bytes. Bugger me if I know why.
answer = answer >> 8 | answer << 8 & 0xff00
return answer
#----------------------------------------------------------------------------------------#
#----> RECEIVE PINGS: polling on all open sockets
#----------------------------------------------------------------------------------------#
def receive_pings():
"""
Receive the ping from the socket.
"""
whatReady = select.select(my_socket_list, [], [], 1000)
if whatReady[0] != []:
print whatReady[0]
for skt in whatReady[0]:
# time evaluation
if IS_WIN:
timeReceived = time.clock()
else:
timeReceived = time.time()
# get datas
(recPacket, addr) = skt.recvfrom(PACKET_SIZE + 64)
icmpHeader = recPacket[20:28]
(type, code, checksum, packetID, sequence) = struct.unpack('bbHHh', icmpHeader)
print addr
if type == 0:
bytesInDouble = struct.calcsize('d')
timeSent = struct.unpack('d', recPacket[28:28 + bytesInDouble])[0]
print "DEST: %s - RTT: %s"%(addr[0],str(timeReceived-timeSent))
elif type == 3:
codes = {
0: 'Net Unreachable',
1: 'Host Unreachable',
2: 'Protocol Unreachable',
3: 'Port Unreachable',
}
raise Exception(codes[code])
break
#----------------------------------------------------------------------------------------#
#----> SEND PING
#----------------------------------------------------------------------------------------#
def send_one_ping(my_socket, dest_addr, ID):
# Header is type (8bit), code (8bit), checksum (16bit), id (16bit), sequence (16bit)
my_checksum = 0
# Make a dummy heder with a 0 checksum.
header = struct.pack('bbHHh', ICMP_ECHO_REQUEST, 0, my_checksum, ID, 1)
bytesInDouble = struct.calcsize('d')
data = (PACKET_SIZE - len(header) - bytesInDouble) * 'x'
if IS_WIN:
start = time.clock()
else:
start = time.time()
data = struct.pack('d', start) + 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 + data
print my_socket
while packet:
sent = my_socket.sendto(packet, (dest_addr, 1)) # Don't know about the 1
packet = packet[sent:]
print "PING SENT TO %s"%dest_addr
#----------------------------------------------------------------------------------------#
#----> DO ONE: socket creation and ping sending
#----------------------------------------------------------------------------------------#
def send_pings():
i = 1
for skt in my_socket_list:
print i
send_one_ping(skt, dests_list[i-1], i)
i+=1
seq_num=+1
#----------------------------------------------------------------------------------------#
#----> SCHEDULE PING: open socket towards a specific destination
#----------------------------------------------------------------------------------------#
def sockets_opening(Ndests):
try:
if sys.platform[0:-2] == 'win':
IS_WIN = True
else:
IS_WIN = False
for i in range(0,Ndests):
icmp = socket.getprotobyname('icmp')
my_socket_list.append(socket.socket(socket.AF_INET, socket.SOCK_RAW,icmp))
print "O2: %s"%my_socket_list[i]
except socket.error, (errno, msg):
if errno == 1: # operation not permitted
msg = msg + ' - Note that ICMP messages can only be sent from processes running as root.'
raise socket.error(msg)
raise # raise the original error
def sockets_closing():
try:
for skt in my_socket_list:
print "C2: %s"%skt
skt.close()
except socket.error, (errno, msg):
print "ERR:%d -> %s"%(errno,msg)
raise
#----------------------------------------------------------------------------------------#
#----> MAIN
#----------------------------------------------------------------------------------------#
if __name__ == '__main__':
print
sockets_opening(N_DESTS)
send_pings()
#time.sleep(3)
receive_pings()
sockets_closing()
输出-->
CREATED-SOCKETS:[<socket._socketobject object at 0xb7267df4>, <socket._socketobject object at 0xb7267e2c>]
PING SENT TO 173.194.41.70
PING SENT TO 213.92.16.101
READY-SOCKETS:[<socket._socketobject object at 0xb7267df4>, <socket._socketobject object at 0xb7267e2c>]
DEST: 173.194.41.70 - RTT: 0.00797414779663
DEST: 173.194.41.70 - RTT: 0.00811314582825
C2: <socket._socketobject object at 0xb7267df4>
C2: <socket._socketobject object at 0xb7267e2c>
代码链接:PingSKT.py