某排程使用以下程式碼產生 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 192168.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,因此將執行以下動作:
- 嘗試解析 IP 位址,若 hostNameOrAddress 傳入的是有效 IP 位址字串,轉成 IP 位址物件不是問題
- 利用 IP 反查取得主機名稱存入 HostName
- 利用主機名稱查詢該主機的所有 IP 位址,存入 AddressList
今天出錯的關鍵在於程式原本所在的正式與測試主機與 192.168.1.1 隸屬同一網域,而問題主機則屬於另一個網域,兩個網域雖有信任關係,但 WINS 及 DNS 反查未打通,故在進行第 2 步以 IP 反查 HostName 時踏到鐵板,產生 No such host is known 錯誤。
知道原因就好辦,有幾種解決方法:
- 設定 system32/drivers/etc/hosts 讓 192.168.1.1 能反查到主機名稱
- 改用 FQDN,GetHostEntry() 改成用 FQDN 解析 IP(DNS 解析的功能是好的)
- 修改程式,當 remoteHost 為 IP 位址時不走 GetHostEntry(),改用 IPAddress.Parse()
最後採行方案 2,問題排除。