传递无效主机名

时间:2015-07-10 07:53:21

标签: c# ntp

我使用以下代码查询NTP服务器。这段代码工作正常,直到我为NTP服务器传递一个无效的主机名:那么这段代码需要很长时间。

const string ntpServer = "pool.ntp.org";

var ntpData = new byte[48];           
ntpData[0] = 0x1B; //LeapIndicator = 0 (no warning), VersionNum = 3 (IPv4 only), Mode = 3 (Client Mode)       

var addresses = Dns.GetHostEntry(ntpServer).AddressList;            
var ipEndPoint = new IPEndPoint( addresses[0] , 123);
var socket = new Socket(AddressFamily.InterNetwork, SocketType.Dgram,  ProtocolType.Udp);    

socket.Connect(ipEndPoint);
socket.Send(ntpData);
socket.Receive(ntpData);
socket.Close();

ulong intPart = (ulong)ntpData[40] << 24 | (ulong)ntpData[41] << 16 | (ulong)ntpData[42] << 8 | (ulong)ntpData[43];
ulong fractPart = (ulong)ntpData[44] << 24 | (ulong)ntpData[45] << 16 | (ulong)ntpData[46] << 8 | (ulong)ntpData[47];

var milliseconds = (intPart * 1000) + ((fractPart * 1000) / 0x100000000L);
var networkDateTime = (new DateTime(1900, 1, 1)).AddMilliseconds((long)milliseconds);
Label1.Text = networkDateTime.ToString();

我收到以下错误

  

在&#39; /&#39;中显示以下错误msgServer错误应用。没有这样的主机已知说明:在执行当前Web请求期间发生了未处理的异常。请查看堆栈跟踪以获取有关错误及其源自代码的位置的更多信息。异常详细信息:System.Net.Sockets.SocketException:未知此类主机源错误:第26行:ntpData [0] = 0x1B; // LeapIndicator = 0(无警告),

1 个答案:

答案 0 :(得分:3)

更新 - 新信息

啊,你得到的等待可能是由于DNS超时尝试解析主机地址。

您获得的错误可能是因为无法解析域名。

参与编写防御性代码的做法是一个好主意。无论在哪里都有可能出现空值,抛出异常或做出假设。

原始回答

UDP是一种无连接协议,没有任何内置的错误处理。

由于您的代码使用UDP,因此不知道它是否成功向NTP服务器发送了请求,并且默认情况下将永远等待响应。我猜你自己正在杀死这个过程。

你唯一能做的就是设置一个ReceiveTimeout并捕捉异常。

const string ntpServer = "pool.ntp.org";
const int timeout = 2000;

var ntpData = new byte[48];           
ntpData[0] = 0x1B; //LeapIndicator = 0 (no warning), VersionNum = 3 (IPv4 only), Mode = 3 (Client Mode)       

IPHostEntry dnsLookup = null;
try {
    dnsLookup = Dns.GetHostEntry(ntpServer);
}
catch(Exception e){ //Better to catch specific types of exceptions
    Label1.Text = string.Format("Unable to resolve hostname: {0}, ntpServer)";
}

if (dnsLookup == null || dnsLookup.AddressList.Length == 0){
    return;
}

var ipEndPoint = new IPEndPoint(dnsLookup.AddressList[0], 123);
var socket = new Socket(AddressFamily.InterNetwork, SocketType.Dgram,  ProtocolType.Udp);    

// wait two seconds before timing out
socket.ReceiveTimeout = timeout; 

try{
    socket.Connect(ipEndPoint);
    socket.Send(ntpData);

    socket.Receive(ntpData);
    ulong intPart = (ulong)ntpData[40] << 24 | (ulong)ntpData[41] << 16 | (ulong)ntpData[42] << 8 | (ulong)ntpData[43];
    ulong fractPart = (ulong)ntpData[44] << 24 | (ulong)ntpData[45] << 16 | (ulong)ntpData[46] << 8 | (ulong)ntpData[47];

    var milliseconds = (intPart * 1000) + ((fractPart * 1000) / 0x100000000L);
    var networkDateTime = (new DateTime(1900, 1, 1)).AddMilliseconds((long)milliseconds);
    Label1.Text = networkDateTime.ToString();
}
catch(Exception e){ //Better to catch specific types of exceptions
    Label1.Text = string.Format("Unable to get time from NTP server: {0}, ntpServer)";
}
finally{
    socket.Close();
}