Доброго времени суток. Написал небольшой скрипт на Ruby, подобие traceroute. Писал под Mac OS, все работало. Проверил в виртуальной машине на Win XP — все ок. Когда пришло время показать это добро, попытался запустить на Windows 7 — облом. После недолгой отладки стало понятно, что проблема в месте вызова recvfrom, функция вылетает по тайм-ауту, пакеты не принимаются. Причем только в Windows 7 x64, на OS X Lion и Windows XP все работает прекрасно. Фаерволл отключил, не помогло. В чем может быть проблема?
#!/usr/bin/env ruby<br>
<br>
require 'timeout'<br>
require 'socket'<br>
<br>
def trace host<br>
port = 33434<br>
ttl = 58<br>
check = 1<br>
errn = 0<br>
errr = 0<br>
reached = 0<br>
puts '* Checking ' + host<br>
puts '|\\'<br>
while ttl <= 255 and reached == 0 do<br>
# recv sock init<br>
recv_sock = Socket.new( Socket::PF_INET, <br>
Socket::SOCK_RAW, <br>
Socket::IPPROTO_ICMP )<br>
recv_sockaddr = Socket.pack_sockaddr_in( port, '' )<br>
recv_sock.bind( recv_sockaddr )<br>
# send sock init<br>
send_sock = UDPSocket.new<br>
send_sock.setsockopt( Socket::IPPROTO_IP, Socket::IP_TTL, ttl )<br>
# sending<br>
send_time = Time.now<br>
send_sock.send( '', 0, host, port )<br>
begin<br>
Timeout::timeout( 1 ) {<br>
# receiving<br>
data, sender = recv_sock.recvfrom( 8192 )<br>
recv_time = Time.now<br>
icmp_type = data.unpack( '<hh user=20C>' )[0]<br>
icmp_code = data.unpack( '<hh user=21C>' )[0]<br>
# show result<br>
rtt = ( recv_time.to_f - send_time.to_f ) * 1000<br>
addr = Socket.unpack_sockaddr_in( sender )[1].to_s<br>
begin<br>
paddr = addr.split('.').collect { |a| a.to_i() }<br>
name = Socket.gethostbyaddr( paddr.pack('CCCC') )[0]<br>
rescue<br>
name = addr<br>
end <br>
puts '|* ' + name + ' ( ' + addr + ' ) ' \<br>
+ 'TIME=' + rtt.round.to_s + ' TTL=' + ttl.to_s<br>
if ( icmp_type ==3 and icmp_code == 13 )<br>
puts '|* Prohibited'<br>
elsif ( icmp_type == 3 and icmp_code == 3 )<br>
puts '|* Destination reached'<br>
reached = 1<br>
end<br>
errr = 0<br>
}<br>
rescue Timeout::Error<br>
if check == 1<br>
check = 0<br>
ttl = 0<br>
puts '|* Host is unreacheble. Starting trace...'<br>
else<br>
puts '|* Timeout TTL=' + ttl.to_s<br>
errn += 1 if errr == 1<br>
break if errn > 1<br>
end<br>
errr = 1<br>
end<br>
ttl += 1<br>
end<br>
puts '|/'<br>
end<br>
<br>
first = ARGV.shift || 'localhost'<br>
last = ARGV.shift || first<br>
<br>
puts '> Checking hosts between ' + first + ' and ' + last<br>
<br>
i = first.split('.')<br>
j = last.split('.')<br>
<br>
while i[3].to_i <= j[3].to_i do<br>
trace i.join('.')<br>
i[3] = i[3].to_i + 1<br>
end<br>
<br>
puts '> Finished!'