某排程使用以下程式碼產生 IEndPoint 以建立 Socket:

IPEndPoint pEndPoint = new IPEndPoint(Dns.GetHostEntry(remoteHost).AddressList[0], remotePort);

其中用了 Dns.GetHostEntry(),好處是不管 remoteHost 傳入的是主機名稱還是 IP,一律可轉成 IPAddress。

排程在正式及測試環境運作多時,今天將程式移到另一網段機器上執行,remoteHost 為 IP 位址(假設為 192.168.1.1),與原本設定相同,確認新主機與 192.168.1.1 間網路暢通,甚至用 telnet 192.168.1.1 portNo 建立連線也成功,但程式一執行就出現以下錯誤:

[SocketException (0x2af9): No such host is known]
   System.Net.Dns.InternalGetHostByAddress(IPAddress address, Boolean includeIPv6) +2221072
   System.Net.Dns.GetHostEntry(String hostNameOrAddress) +6671028

認真看了 MSDN 文件,搞懂 GetHostEntry() 邏輯才恍然大悟。

GetHostEntry 的介面為:

public static IPHostEntry GetHostEntry(
    string hostNameOrAddress
)

其中 hostNameOrAddress 參數可以是主機名稱也可以是 IP 位址。當傳入 IP 時 GetHostEntry 假設程式想取得 IPHostEntry 的完整資訊-包含 AddressList, Aliases, 與 HostName,因此將執行以下動作:

  1. 嘗試解析 IP 位址,若 hostNameOrAddress 傳入的是有效 IP 位址字串,轉成 IP 位址物件不是問題
  2. 利用 IP 反查取得主機名稱存入 HostName
  3. 利用主機名稱查詢該主機的所有 IP 位址,存入 AddressList

今天出錯的關鍵在於程式原本所在的正式與測試主機與 192.168.1.1 隸屬同一網域,而問題主機則屬於另一個網域,兩個網域雖有信任關係,但 WINS 及 DNS 反查未打通,故在進行第 2 步以 IP 反查 HostName 時踏到鐵板,產生 No such host is known 錯誤。

知道原因就好辦,有幾種解決方法:

  1. 設定 system32/drivers/etc/hosts 讓 192.168.1.1 能反查到主機名稱
  2. 改用 FQDN,GetHostEntry() 改成用 FQDN 解析 IP(DNS 解析的功能是好的)
  3. 修改程式,當 remoteHost 為 IP 位址時不走 GetHostEntry(),改用 IPAddress.Parse()

最後採行方案 2,問題排除。


Comments

# by flyjackey

你好我也遇到一樣的問題 我的網域是162.168.2.xxx 我的PC IP是192.168.2.27 我要scan 所屬網域的所有有效的IP address (用Ping) 當我ping 到192.168.2.121為有回應的IP但是當我用GetHostEntry("192.168.2.121") 時會發生Exception 錯誤訊息是"無法識別這台主機"請問您說的方法2 改用FQDN是要怎麼做? 我找不到相關的做法 可以麻煩您稍微說明一下嗎 感謝

# by flyjackey

附帶一提,出問題的IP位址是給手機的,我用方法一可以解決但是,但是我覺得這不是好的方法,想用程式解決可以請問我該怎麼做呢?

# by Jeffrey

to flyjackey, 方法二需要DNS配合,跑Scan程式所指向的DNS要能用該IP反查出機器名稱,如果DNS主機是AD網域控制器還單純些,若非網域機器則要請DNS管理者手動加記錄,反而麻煩。 如果你的情境是用迴圈列舉方式Scan有效IP,Dns.GetHostEntry()通吃IP、機器名稱、FQDN的特性派不上用場,我建議改用 IPAddress.Parse()就好。

Post a comment