
我有一台有 2 個網路介面的 Windows 10 電腦。其中一個介面進入檔案伺服器、DNS 和網際網路路由器所在的主 LAN。第二個介面是一個微型 LAN,其中包含 PLC 和 HMI。它們在物理上位於同一區域網路中,但位於不同的子網路中(抱歉,無法更改這一點,超出了我的控制範圍)。
所以我有兩個實體介面和一個邏輯介面:eth0:DHCP,172.16.xy,MASK 255.255.255.0,預設gw 172.16.xz eth1:靜態192.168.1.158,MASK 255.255.2525.051525.0595.593195.593132533333331333333393939393939393333393個。 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 的另一個回應。
看來,XP 之後的 Windows 開始執行一些“路由魔法”,如果無法通過更具體的路由到達目標,則僅將資料發送到預設路由。好像其他也有過這個問題
我發現一些“解決方案”對我來說並不是真正的解決方案(更多內容見下文)
- 所以 ping 有一個很好的“-S”參數來定義來源位址。是的,這「解決」了問題。如果 HMI 啟動,我會立即收到回覆。但我在 powershell 腳本中使用該命令,並且「測試連接」的來源參數具有完全不同的含義。由於我在腳本中使用它,一旦本地 IP 發生更改,就會失敗。
- 我靜態配置 eth0 而不是透過 DHCP,也沒有定義預設路由。這也「解決」了問題(我想你可以想像為什麼這不是真正的解決方案)
- 我只是理論上對此進行了探索,但我可以安裝一個基於Linux的路由器,在PC、LAN和帶有PLC和HMI的隔離LAN之間有3個接口,並讓它完成所有路由(這肯定會解決問題! 但老實說,我是否需要一台額外的電腦來解決損壞的 Windows 路由問題?
- 'arp -d *' 似乎也有幫助,但需要提升權限
我嘗試添加具有不同參數和指標的靜態路由。不用找了!靜態新增 HMI 的 MAC 沒有幫助,因為該 MAC 可能會變更。
所以我的問題是:
- 有沒有關於 Windows 中這種行為變化的文檔?
- 有沒有辦法強制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 試圖變得過於智能而不顧自己的利益)。以美元計?我知道最後一個命令返回成功,如果失敗則返回 false。所以從那以後就很容易處理了。
據我所知,微軟沒有關於這種行為以及如何處理它的文檔,我認為這非常可悲。