Pythonでマルチpingコードを実装しようとしていますが、問題は、次のコードでは、定義した両方のソケットが同じ宛先から同じパケットを受信しているように見えることです! なぜそれが起こるのですか?うーん
- - - - - - - - - - アップデート - - - - - - - - - -
受信したパケットは常に「最も速い」パケット [つまり、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
- - - - - - - - - - アップデート - - - - - - - - - -
CODE --> [フォーマットの問題を避けるために、投稿の最後にダウンロード可能なバージョンがあります]
#!/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