我有一个带有UTC时间戳的缓冲区,我每十秒钟就会播放一次缓冲区。问题是两个数据包之间的时差不一致。经过5到10次迭代后,时差变为9,11,然后再次为10.请帮助我解决这个问题。
我正在使用<time.h>
作为UTC时间。
答案 0 :(得分:3)
如果你的时间戳只有1秒的分辨率,那么最低有效数字总是会有+/- 1的不确定性(在这种情况下是+/- 1秒)。
澄清:如果您只有1秒的分辨率,那么您的时间值为quantized
。由这样的量化值表示的实时t
具有t..t+0.9999
的范围。如果你取两个这样的时间差t0
和t1
,则t1-t0
中的最大误差为-0.999..+0.999
,量化后的+/-1
秒。因此,在您的情况下,您可能会看到9..11
秒范围内的差值。
答案 1 :(得分:1)
睡眠时间为X毫秒的线程无法保证正好睡眠很多毫秒。我假设你的陈述类似于:
while(1) {
...
sleep(10); // Sleep for 10 seconds.
// fetch timestamp and send
}
如果您在循环检查中睡眠时间较短(比如20毫秒),您将获得更准确的时间表,直到时间结束。当您休眠10秒钟时,您的线程会进一步移出基础操作系统的即时调度优先级。
您还可以考虑发送时间戳所花费的时间可能会有所不同,具体取决于网络状况等,如果你睡觉(10) - > send - &gt; sleep(10)类型的循环,发送时间将实际添加到下一次睡眠(10)。
尝试这样的事情(原谅我,我的C有点生锈):
bool expired = false;
double last, current;
double t1, t2;
double difference = 0;
while(1) {
...
last = (double)clock();
while(!expired) {
usleep(200); // sleep for 20 milliseconds
current = (double)clock();
if(((current - last) / (double)CLOCKS_PER_SEC) >= (10.0 - difference))
expired = true;
}
t1 = (double)clock();
// Set and send the timestamp.
t2 = (double)clock();
//
// Calculate how long it took to send the stamps.
// and take that away from the next sleep cycle.
//
difference = (t2 - t1) / (double)CLOCKS_PER_SEC;
expired = false;
}
如果您不打算使用标准C库,可以考虑使用Windows的高分辨率计时器功能,例如QueryPerformanceFrequency / QueryPerformanceCounter函数。
LONG_INTEGER freq;
LONG_INTEGER t2, t1;
//
// Get the resolution of the timer.
//
QueryPerformanceFrequency(&freq);
// Start Task.
QueryPerformanceCounter(&t1);
... Do something ....
QueryPerformanceCounter(&t2);
// Very accurate duration in seconds.
double duration = (double)(t2.QuadPart - t1.QuadPart) / (double)freq.QuadPart;