NTP UDP套接字不接收任何数据,因此方法永远不会返回

时间:2013-10-28 17:31:55

标签: c# sockets ntp

我正在使用这种在C#中返回NTP时间作为DateTime对象的实现: https://stackoverflow.com/a/12150289/559988

然而,由于这是在我无法控制的网络上的许多计算机上的软件中部署的,因此问题变得有时NTP有时会在这些网络上被阻止。因此,当调用该方法时,它似乎永远不会返回,因为它永远不会获得任何数据。

我尝试按如下方式实现超时:

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");
}

但是超时不起作用,因为该方法没有返回。

有谁知道如何为Socket实现超时,以便我至少可以故障转移到另一种检查NTP时间的方法?

由于

编辑:只是为了澄清是否没有网络连接(即你禁用你的适配器)它会立即失败就好了。这是一个网络问题,一些网络正在阻止NTP协议(我认为)导致套接字打开但挂起在任一连接上或等待接收数据。

1 个答案:

答案 0 :(得分:2)

我相信你实施的超时不起作用,因为该方法总是立即返回。

UDP协议是无连接的。当您在UDP套接字上调用Connect()时,实际上没有任何事情发生,您只需设置一个默认端点,这样就不会在每次Send()呼叫时重复自己。

Send()调用也会很快返回,即使远程主机无法访问也是如此。在这种情况下,数据将丢失,这就是UDP的工作方式。

底线: 您需要在Receive()电话上实施超时:

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");
}