3

I am using the code below for querying an NTP server. This code is working fine until I pass an invalid hostname for the NTP server: then this code takes a very long time.

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();

I'm getting the following error

show following error msgServer Error in '/' Application. No such host is known Description: An unhandled exception occurred during the execution of the current web request. Please review the stack trace for more information about the error and where it originated in the code. Exception Details: System.Net.Sockets.SocketException: No such host is known Source Error: Line 26: ntpData[0] = 0x1B; //LeapIndicator = 0 (no warning),

phuzi
  • 12,078
  • 3
  • 26
  • 50
Gaurav Pal
  • 77
  • 6

1 Answers1

3

UPDATE - New information

Ah, the wait you're getting is probably due to DNS timing out try to resolve the host address.

The error you're getting is probably because the domain name cannot be resolved.

It's a good idea to get in to the practice of writing defensive code. Wherever there's the possibility of something being null, throwing an exception or you make an assumption.

Original answer

UDP is a connectionless protocol that doesn't have any built in error handling.

Since your code uses UDP it has no idea about whether it successfully sent an request to the NTP server or not and will, by default, wait forever for a response. I'm guessing you're killing the process yourself.

The only thing you can do is set a ReceiveTimeout and catch the exception when it does.

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();
}
phuzi
  • 12,078
  • 3
  • 26
  • 50
  • 3
    You managed to get the problem from that description? I am impressed – fk2 Jul 10 '15 at 08:36
  • @fk2 UDP can be a PITA – phuzi Jul 10 '15 at 08:40
  • not throw exception in label. show following error msgServer Error in '/' Application. No such host is known Description: An unhandled exception occurred during the execution of the current web request. Please review the stack trace for more information about the error and where it originated in the code. Exception Details: System.Net.Sockets.SocketException: No such host is known Source Error: Line 26: ntpData[0] = 0x1B; //LeapIndicator = 0 (no warning), – Gaurav Pal Jul 10 '15 at 08:44
  • @GauravPal A critical bit of information, please add it to your question. – phuzi Jul 10 '15 at 08:54
  • @GauravPal Updated my answer given new information. – phuzi Jul 10 '15 at 09:16
  • @phuzi I still fail to see what the actual question/intended behavior is. "I'm adding a random non-NTP-server that may or may not exist into my NTP-server code and get host-resolve errors" seems to be everything working as intended – fk2 Jul 10 '15 at 09:31
  • @fk2 Managed to replicate the error by using an invalid hostname, try adding a space to the end of the hostname `"pool.ntp.org "` – phuzi Jul 10 '15 at 09:40
  • Today i am facing new problem regarding this. I am host my code on server and getting date Mon, 01 Jan 1900 00:00 from the above code. but this code working properly in local host. – Gaurav Pal Jul 13 '15 at 10:29
  • Sounds like `ntpData` is all zero, could be another question - BTW, did my answer help you solve your original problem? – phuzi Jul 13 '15 at 10:37