在编写跨平台时钟同步服务时,犯了一个经典低级错误,和大家共同分享
原来函数大概实现是这样的:计算客户端和时间服务器误差delta值(以秒为单位),用该值修正本地时钟
int update(long delta)
{
#ifdef _WIN32
// use SetLocalTime() to change time
SYSTEMTIME st;
FILETIME ft;
ULARGE_INTEGER ui;
::GetLocalTime(&st);
::SystemTimeToFileTime(&st,&ft);
ui.LowPart=ft.dwLowDateTime;
ui.HighPart=ft.dwHighDateTime;
ui.QuadPart+=(delta*10000000);
ft.dwLowDateTime=ui.LowPart;
ft.dwHighDateTime=ui.HighPart;
::FileTimeToSystemTime(&ft,&st);
if (::SetLocalTime(&st))
{
//write success log
return 0;
}else{
//write fail log
return -1;
}
}
调试发现当误差超过一定值同步行为就比较诡异了,相信细心的程序员早就发现问题出在哪儿了
下面是修改之后的代码
int update(long delta)
{
#ifdef_WIN32
// use SetLocalTime() to change time
SYSTEMTIME st;
FILETIME ft;
ULARGE_INTEGER ui;
__int64 delta64=delta;
::GetLocalTime(&st);
::SystemTimeToFileTime(&st,&ft);
ui.LowPart=ft.dwLowDateTime;
ui.HighPart=ft.dwHighDateTime;
ui.QuadPart+=(delta64*10000000);
ft.dwLowDateTime=ui.LowPart;
ft.dwHighDateTime=ui.HighPart;
::FileTimeToSystemTime(&ft,&st);
if (::SetLocalTime(&st))
{
//write success log
return 0;
}else{
//get last error and write fail log
return -1;
}
}
调试现象就是当客户端和主机误差超过一定范围时,显示同步成功,但是时钟误差并未正确修正,原因比对前后代码就很清楚了