Pergunta

I'm using this implementation of returning NTP time as a DateTime object in C#: https://stackoverflow.com/a/12150289/559988

However as this is deployed in software on many computers on networks I don't control, the issue becomes that sometimes NTP is sometimes blocked on those networks. Thus when that method is called it never seems to return because it never gets any data back.

I tried to implement a timeout as follows:

IAsyncResult result = socket.BeginConnect(ipEndPoint, null, null);
Boolean success = result.AsyncWaitHandle.WaitOne(15000,true);
if (!success)
{
     socket.Close();
     throw new ApplicationException("Failed to connect to NTP server within 15 seconds");
}

But the timeout doesn't work because the method doesn't return.

Does anyone know how I can implement a timeout for a Socket so that I can at least fail over to another method of checking the NTP time?

Thanks

Edit: Just to clarify if there's no network connection (ie. you disable your adapter) it fails straight away just fine. It's a network issue where some networks are blocking the NTP protocol that (I think) causes the socket to open but hang on either connection or waiting on receiving data.

Foi útil?

Solução

I believe the timeout you implemented doesn't work because the method always returns immediately.

The UDP protocol is connectionless. When you call Connect() on an UDP socket, nothing really happens, you're just setting a default endpoint so you don't repeat yourself on each Send() call.

The Send() call also returns pretty quickly, even if the remote host is unreachable. In which case the data would be lost and this is how UDP is meant to work.

The bottom line: You need to implement a timeout on the Receive() call:

var result = socket.BeginReceive(ntpData, 0, ntpData.Length, SocketFlags.None, null, null);
var success = result.AsyncWaitHandle.WaitOne(15000);
if (!success)
{
    socket.Close();
    throw new ApplicationException("Failed to connect to NTP server within 15 seconds");
}
Licenciado em: CC-BY-SA com atribuição
Não afiliado a StackOverflow
scroll top