我的C#应用程序中存在时间戳问题.我异步地从远程TCP连接接收数据.每次收到数据时,我都会将时间戳变量更新为DateTime.Now.在一个单独的线程上,每秒一次,我检查它是否超过自我上次收到后的预定义超时时间,如果是,则断开连接.这种方法已经工作了很多年,但现在我的情况是应用程序安装在具有不稳定时间源的机器上.每隔几天,机器时间"自动校正",我提前断开连接.代码基本如下:
void OnReceiveComplete(IAsyncResult ar) {
...
mySocket.EndReceive(ar);
lastRxTime = DateTime.Now;
...
}
Run Code Online (Sandbox Code Playgroud)
void CheckConnection() {
TimeSpan ts = DateTime.Now.Subtract(lastRxTime);
if(ts.TotalMilliseconds > timeout) {
Disconnect(string.Format("No packet received from the server for over {0} seconds.", timeout / 1000));
}
}
Run Code Online (Sandbox Code Playgroud)
在问题发生期间我有有效的Wireshark捕获,在断开连接之前我看到NTP流量最终看起来像是至少1分钟的修正.这显然会导致检查过程失败.
我的谷歌搜索到目前为止导致以下结果:
DateTime.UtcNow而不是DateTime.Now出于性能原因.这不会影响问题本身.Environment.TickCount和Stopwatch.GetTimestamp()Environment.TickCount可能会受到时间调整的影响,但我不确定在什么情况下.此外,由于我在其他更高性能的情况下使用相同的方法,10-16毫秒的分辨率可能是一个问题(虽然不是我在这里提出的具体情况).Stopwatch.GetTimestamp()可以回退DateTime.Now.Ticks.我不确定这种情况会发生多久(任何机器都不再配备高性能时钟),但我确信如果它转向Ticks会出现同样的问题.Stopwatch.GetTimestamp()将使用QueryPerformanceCounter()API调用,并且从多个线程调用时可能会不稳定.我很好奇生成lastRxTime时间戳的最佳方法是什么?我是否过分担心 …