Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/python/339.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
python中跟踪路由的实现_Python_Python 3.x_Sockets_Networking - Fatal编程技术网

python中跟踪路由的实现

python中跟踪路由的实现,python,python-3.x,sockets,networking,Python,Python 3.x,Sockets,Networking,我一直在尝试为python编写一个简单的跟踪路由实现;请在下面查找代码 import socket def main (HostName): dest_addr = socket.gethostbyname(HostName) TTL = 1 #Define the time to live as 1. Will be incremented by one after each UDP message has been sent Max = 30 while

我一直在尝试为python编写一个简单的跟踪路由实现;请在下面查找代码

import socket

def main (HostName):
    dest_addr = socket.gethostbyname(HostName)
    TTL = 1    #Define the time to live as 1. Will be incremented by one after each UDP message has been sent
    Max = 30



while True:
    ICMP_socket = socket.socket(socket.AF_INET,socket.SOCK_RAW, socket.IPPROTO_ICMP) #Create socket that can receive ICMP 
    UDP = socket.socket(socket.AF_INET, socket.SOCK_DGRAM, socket.IPPROTO_UDP) #Create socket that will send UDP messages 
    UDP.setsockopt(0,4,TTL)
    
    
    
    ICMP_socket.bind(("",33434)) #33434 is the default port used for traceroute 
    message = "Hi" #The message we send is an empty string 
    UDP.sendto(message.encode(),(dest_addr, 33434))
    
   
    
    Receiver = (0,"")
    Router_addr = None
    
    
    try:
        Receiver = ICMP_socket.recvfrom(1024)
        Router_addr = Receiver[1]
        if Router_addr == None:
            print("*")
        else:
            print(Router_addr)
    except:
        pass
    finally:
        ICMP_socket.close()
        UDP.close()
    
    TTL = TTL + 1
    
    if Router_addr == dest_addr or TTL == Max:
        break
    
    
if __name__ =="__main__":
    main('google.com')
我用sudo在macOS终端上运行它,因为它需要root权限。然而,我得到的输出似乎是错误的。第一个IP是我的本地IP,第二个是我不知道的IP,其余的都是谷歌的IP。它不输出中间IP,只有在达到TTL限制30时才断开

这是输出(我删除了第一个Ip,即本地Ip地址):

有人能帮忙吗?我似乎找不到问题所在


谢谢大家!

为什么程序不停止

程序在“到达”目的地时不会停止,因为您忽略了
地址
,您称之为
路由器地址
,因为
AF\u INET
是一个
元组
(请参阅中的“套接字系列”)。您在问题中包含的输出也可以看出这一点(这是
打印(Router\u addr)
的结果)

如果您将路由器地址==dest\u addr或TTL==Max:更新为如下所示,您的程序将停止

如果路由器地址[0]==dest\u addr或TTL==Max:
输出显示了什么

我不知道你的网络拓扑结构,也不知道你是如何进入互联网的,尤其是谷歌。根据您在输出中描述和看到的内容

  • 172.30.224.110
    是供应商路由器内部接口(很可能)的专用IP地址;回想一下,响应是从离您“更近”的接口发送到您的计算机的,而不是从离Internet“更近”的接口发送到您的计算机的(我假设,正如您所提到的,您不认为此IP地址属于您的[例如,家庭、大学]路由器/网络)
  • 谷歌IP地址(172.217.19.46)和上面的路由器之间可能没有多跳;例如,如果谷歌的服务器位于您的提供商的网络上(对于大型内容提供商和CDN来说,实现对大型眼球提供商终端用户的高性能是一种非常常见的做法),则可能出现这种情况;在我的机器上,我看到运行你的程序的多个google跳转(也许你想检查另一个目的地)
  • 最不清楚的一点是,为什么在第一行看到机器的IP地址;这可能是因为您将Mac用作路由器(可能用于Internet共享)或处于涉及转发的“奇怪”配置中(因此第一个路由器就是您的机器);我在此假设,当您谈论您的本地IP地址时,您不是指环回IP地址(否则请阅读下文)
为什么环回地址在输出中

如果您在路径中看到的某些网络主机(可能包括您的第一个跃点)是环回IP地址,而不是您将数据包发送到的地址,那么原因是下面的代码片段(以及在后台发生的情况):

如果路由器地址==无:
打印(“*”)
当网络节点没有响应时,socket.recvfrom()返回
('127.0.0.1',0)
,它不是
None
。这是因为对于
UDP
而言,当目标端口上没有任何内容侦听时,
localhost
会生成一个
ICMP目标不可访问
(类型3)
端口不可访问
(代码3)。顺便说一下,这就是为什么
ICMP\u socket.recvfrom(1024)
不会被阻止的原因

您的更正程序经过轻微修改以打印
TTL
s和
ICMP
类型和代码,给出了(请参见,
TTL:[6]
):

$sudo python3 trorig.py
('192.168.178.1',0)TTL:[1]类型:[11]代码:[0]
('62.245.142.131',0)TTL:[2]类型:[11]代码:[0]
('62.245.142.130',0)TTL:[3]类型:[11]代码:[0]
('82.135.16.226',0)TTL:[4]类型:[11]代码:[0]
('142.250.161.214',0)TTL:[5]类型:[11]代码:[0]
('127.0.0.1',0)TTL:[6]类型:[3]代码:[3]
('172.253.75.128',0)TTL:[7]类型:[11]代码:[0]
('172.253.75.143',0)TTL:[8]类型:[11]代码:[0]
('74.125.244.81',0)TTL:[9]类型:[11]代码:[0]
('172.253.75.141',0)TTL:[10]类型:[11]代码:[0]
('172.217.23.78',0)TTL:[11]类型:[3]代码:[3]
相应的tcpdump输出为(请注意,无响应的网络主机没有行,142.250.161.214后跟172.253.75.128,):

相应的traceroute输出是(与上述路径相比,路径存在一些差异,因为没有同时运行它,但要点仍然是,TTL:[6]处的网络主机没有响应):

因此,您在中检查无响应网络主机的方式是不正确的。您可能希望将其更新为以下内容:

if Router_addr == ('127.0.0.1', 0) :
    print("*")
您可能需要考虑的最后两点:

  • 如上所述,并非每个主机(或网络)都会向您发回响应,并且响应可能会丢失或丢失。在放弃并声明网络主机没有响应之前,您可能希望在
    ICMP\u socket.recvfrom(1024)
    中包含您愿意等待多长时间的超时。您可以查看socket.SO\u RCVTIMEO
  • 如上所述,在一个给定的
    TTL
    上,可能有多个网络主机从您的机器向目标移动。您可能需要考虑发送多个包来发现它们(如果它们是可发现的)。
编辑(回答下面的评论):原始代码需要一些小的修改才能正常运行;下面是更新和增强的代码

导入套接字
导入结构
def主(主机名):
dest_addr=socket.gethostbyname(主机名)
TTL=1
最大值=30
尽管如此:
ICMP_socket=socket.socket(socket.AF_INET,socket.SOCK_RAW,socket.IPPROTO_ICMP)
$ sudo tcpdump -i en0 -nnn icmp      
Password:
tcpdump: verbose output suppressed, use -v or -vv for full protocol decode
listening on en0, link-type EN10MB (Ethernet), capture size 262144 bytes
14:30:45.720700 IP 192.168.178.1 > 192.168.178.20: ICMP time exceeded in-transit, length 38
14:30:45.740808 IP 62.245.142.131 > 192.168.178.20: ICMP time exceeded in-transit, length 38
14:30:45.761857 IP 62.245.142.130 > 192.168.178.20: ICMP time exceeded in-transit, length 36
14:30:45.782603 IP 82.135.16.226 > 192.168.178.20: ICMP time exceeded in-transit, length 36
14:30:45.803874 IP 142.250.161.214 > 192.168.178.20: ICMP time exceeded in-transit, length 38
14:30:53.454002 IP 172.253.75.128 > 192.168.178.20: ICMP time exceeded in-transit, length 76
14:30:53.476512 IP 172.253.75.143 > 192.168.178.20: ICMP time exceeded in-transit, length 38
14:30:53.496455 IP 74.125.244.81 > 192.168.178.20: ICMP time exceeded in-transit, length 38
14:30:53.519329 IP 172.253.75.141 > 192.168.178.20: ICMP time exceeded in-transit, length 38
14:30:53.541726 IP 172.217.23.78 > 192.168.178.20: ICMP 172.217.23.78 udp port 33434 unreachable, length 36
$ traceroute -n google.com
traceroute to google.com (172.217.23.78), 64 hops max, 52 byte packets
 1  192.168.178.1  8.694 ms  2.893 ms  3.095 ms
 2  62.245.142.131  17.545 ms  17.361 ms  19.010 ms
 3  62.245.142.130  25.948 ms  20.302 ms  26.077 ms
 4  82.135.16.226  20.418 ms  19.967 ms  21.411 ms
 5  142.250.161.214  29.145 ms  25.573 ms  19.979 ms
 6  * * *
 7  108.170.247.113  26.875 ms
    172.253.75.146  21.736 ms
    108.170.247.113  21.987 ms
 8  172.253.75.143  22.435 ms
    172.253.75.141  20.617 ms
    108.170.247.120  21.670 ms
 9  172.217.23.78  19.538 ms
    74.125.244.97  18.503 ms
    74.125.244.81  18.907 ms
if Router_addr == ('127.0.0.1', 0) :
    print("*")