![Windows 10 忽略路由表](https://linux22.com/image/774558/Windows%2010%20%E5%BF%BD%E7%95%A5%E8%B7%AF%E7%94%B1%E8%A1%A8.png)
我有一台 Windows 10 PC,它有 2 个网络接口。其中一个接口进入主 LAN,文件服务器、dns 和互联网路由器都位于那里。第二个接口是一个小型 LAN,它有一个 PLC 和一个 HMI。它们在物理上都位于同一个 LAN 中,但在不同的子网上(抱歉,无法更改,超出了我的控制范围)。
所以我有两个物理接口和一个逻辑接口: eth0:DHCP,172.16.xy,MASK 255.255.255.0,默认 gw 172.16.xz eth1:静态 192.168.1.158,MASK 255.255.255.0 静态 192.168.19.158,MASK 255.255.255.0
可通过 192.168.19.135 访问 HMI
现在,当我重新启动 HMI 时,我会启动 ping 以查看何时可以再次访问。这应该在大约 30 秒后发生。但我只在 80-90 秒后才收到肯定的 ping 回复。
Ping wird ausgeführt für 192.168.19.135 mit 32 Bytes Daten:
Antwort von 192.168.19.158: Zielhost nicht erreichbar.
Zeitüberschreitung der Anforderung.
Zeitüberschreitung der Anforderung.
Zeitüberschreitung der Anforderung.
(抱歉,使用的是德文,但我认为我们在这里看到的应该还是比较清楚的)我对第一次 ping 的回应与第二次 ping 的回应不同。
似乎 Windows XP 之后开始使用一些“路由魔法”,如果无法通过更具体的路由到达目标,则只通过默认路由发送数据。似乎其他系统也曾有过这个问题
我发现一些“解决方案”对我来说并不是真正的解决方案(更多内容见下文)
- 因此,ping 有一个很好的“-S”参数来定义源地址。是的,这“解决”了问题。如果 HMI 已启动,我会立即收到回复。但我在 powershell 脚本中使用该命令,而“test-connection”的源参数具有完全不同的含义。而且由于我在脚本中使用它,因此只要本地 IP 发生变化,它就会失败。
- 我静态配置了 eth0,而不是通过 DHCP 配置,并且没有定义默认路由。这也“解决”了问题(我想您可以想象为什么这不是真正的解决方案)
- 我只是在理论上探索过这一点,但我可以安装一个基于 Linux 的路由器,在 PC、LAN 和带有 PLC 和 HMI 的隔离 LAN 之间有 3 个接口,并让它完成所有路由(这肯定能解决问题!但说实话,我是否需要一台额外的计算机来解决损坏的 Windows 路由问题?)
- “arp -d *” 似乎也有帮助,但需要提升权限
我尝试添加具有不同参数和度量的静态路由。没有变化!静态添加 HMI 的 MAC 没有帮助,因为这个 MAC 可能会改变。
我的问题是:
- 有没有关于 Windows 中这种行为变化的文档?
- 有没有办法强制窗口使用定义的接口
答案1
因此,在找不到简单的解决方案后,我决定通过编程来解决微软因严重弄乱 Windows 路由而造成的问题。
我只是使用带有参数 -S 的经典 ping 而不是 powershell 中的 cmdlet test-connection
我的代码的 ping 部分现在如下所示:
$localIPs = (Get-NetIPConfiguration -InterfaceAlias "PLC").IPv4Address.IPAddress
# because this command returns a string, when the interface has a single IP-address but an array of strings if the interface has more than one address, we need to check for this
if ($localIPs.GetType().Name -eq "string") { # only a single IP
$localIP = $localIPs
}
else { # more than one IP
$localIP = $localIPs[0] # since it seems that windows does use the ip address as a synonym for the interface, it's not important which of the addresses of that interface we use. So we're just picking the first one
}
$pingcount = 180
do {
ping $HMI4IP -n 1 -w 1000 -S $localIP | Out-Null # redirect the output of ping to /dev/null
$pingreply = $?
$pingcount = $pingcount - 1
}
until ($pingcount -eq '0' -or $pingreply)
if ($pingreply) {
# code here
}
else {
exit 1337 # return with an error code, we've not reached our target
}
为此,我只需确保 PLC 和 HMI 连接的接口名为“PLC”。然后,我将地址作为字符串或地址数组(取决于接口是否有一个或多个地址)来处理(欢迎使用动态类型……)。然后,这就像将这些数据提供给 ping 一样简单(因为 Test-Connection 试图变得过于聪明,以致于自私自利)。在 $? 中,如果最后一条命令返回成功,则返回 true,如果返回失败,则返回 false。因此,从那里开始就很容易处理了。
据我所知,微软没有关于这种行为以及如何处理它的文档,我认为这很可悲。