服务器、客户端全部代码下载:https://download.csdn.net/download/lyhoo163/10703465
一、服务器与客户端的时间同步
我们在编程时,需要让客户端与服务器的时间保存一致(同步),这样,对于数据的查询和处理很有必要。比如,防止用户修改当前时间,造成数据逻辑混乱,客户端使用的时间应为服务器时间。
如何处理呢,我们可以使用Delphi Indy组件中的 TIdDayTimeServer和TIdDayTime一对组件。
TIdDayTimeServer用于服务器端,TIdDayTime用于客户端,二级控件只要参数配置好,随时可以校准二者的时间。
只要我们在客户端,通过Timer定时,读取服务器时间,并保持一致。
二、技术准备
1、在服务器端加入TIdDayTimeServer,大多数使用默认参数。
(1)IdDayTimeServer1.DefaultPort
默认端口:1339(通常默认值)
(2)IdDayTimeServer1.Active
True,启动IdDayTimeServer。
False,关闭IdDayTimeServer。
2、在客户端加入TIdDayTimeServer,大多数使用默认参数。
(1)IdDayTime1.Host
服务器IP地址,
(2) IdDayTime1.Port
服务器端口:与服务器端一致。
(3)IdDayTime1.DayTimeStr
返回时间字符串,格式如下:
“星期六, 十月 06, 2018 12:26:27-EST”
这是正常返回的值,通过分析此格式,通过由该字符串,获取相关日期时间的值。
3、SetLocalTime(SysTime) ,设置本地时间(API)
4、系统时间参数,TSystemTime类型,用于设置本地时间,它的数据结构如下:
TSystemTime = record
wYear: Word;
wMonth: Word;
wDayOfWeek: Word;
wDay: Word;
wHour: Word;
wMinute: Word;
wSecond: Word;
wMilliseconds: Word;
end;
5、分解DayTimeStr获取,标准时间值函数
CopyDateTime(S) // 代码参见下文
三、代码如下:
1、服务器
procedure TForm1.Button1Click(Sender: TObject);
begin
IdDayTimeServer1.DefaultPort := StrToIntDef(Edit1.Text, strtoint(Edit1.Text));
IdDayTimeServer1.Active := True;
Memo1.Lines.Add('服务器启动成功');
end;
procedure TForm1.Button2Click(Sender: TObject);
begin
IdDayTimeServer1.Active := false;
Memo1.Lines.Add('服务器连接断开!');
end;
2、客户端
function TForm1.CopyDateTime(TimeStr:string):String; // CopyDateTime
var SysTime: TSystemTime;
tzInfo: Time_Zone_Information; // 系统参数
hBias, // 小时 偏差
mBias, // 分钟 偏差
First,Last,Top: Integer;
S:string;
i,iYear,iMonth,iDay,iH,iM,iSS:integer;
begin
// 星期六, 十月 06, 2018 12:26:27-EST 格式
// 1 2 3 4 5 6 7 8 子串序号
Result:='';
iYear:=0;
iMonth:=0;
iDay:=0;
iH:=0;
iM:=0;
iSS:=0;
if Length(TimeStr)>30 then
begin
First:=0; // 字符首位
Last:=0; // 字符未位
Top:=0; // 字符序列号
for i:=1 to Length(TimeStr) do
begin
if (TimeStr[i]=' ') or (TimeStr[i]=',') or (TimeStr[i]=':') or
(TimeStr[i]='-') or (i=Length(TimeStr)) then // 断点
begin
First:=Last+1;
Last:=i;
if i'' then
begin
Top:=Top+1;
// showmessage(IntToStr(Top)+': '+S);
if Top=2 then // 处理月
begin
if (S='一月') or (S='Jan') then iMonth:=1;
if (S='二月') or (S='Feb') then iMonth:=2;
if (S='三月') or (S='Mar') then iMonth:=3;
if (S='四月') or (S='Apr') then iMonth:=4;
if (S='五月') or (S='May') then iMonth:=5;
if (S='六月') or (S='Jun') then iMonth:=6;
if (S='七月') or (S='Jul') then iMonth:=7;
if (S='八月') or (S='Aug') then iMonth:=8;
if (S='九月') or (S='Sep') then iMonth:=9;
if (S='十月') or (S='Oct') then iMonth:=10;
if (S='十一月') or (S='Nev') then iMonth:=11;
if (S='十二月') or (S='Dec') then iMonth:=12;
end;
if Top=3 then // 处理日
iDay:=StrToInt(S);
if Top=4 then // 处理年
iYear:=StrToInt(S);
if Top=5 then // 处理时
iH:=StrToInt(S);
if Top=6 then // 处理分
iM:=StrToInt(S);
if Top=7 then // 处理秒
iSS:=StrToInt(S);
end;
end;
end;
end;
// 下面分别向SysTime分解字符串的值
SysTime.wYear:=iYear;
SysTime.wMonth:=iMonth;
SysTime.wDay:=iDay;
SysTime.wHour:=iH;
SysTime.wMinute:=iM;
SysTime.wSecond:=iSS;
SysTime.wMilliseconds:=0;
// 对获取的SysTime时间值 进行修正
SysTime.wYear:=SysTime.wYear; // 加入日期偏差
SysTime.wHour:=SysTime.wHour-hBias; // 加入小时偏差
SysTime.wMinute:=SysTime.wMinute-mBias; // 加入小时偏差
Result:=FormatDateTime('yyyy-mm-dd hh:nn:ss zzz',SystemTimeToDateTime(SysTime));
end;
procedure TForm1.Button1Click(Sender: TObject);
begin
IdDayTime1.Host := Edit1.Text; // 连接主机
IdDayTime1.Port := StrToIntDef(Edit2.Text,strtoint(Edit2.Text)); // 端口
end;
procedure TForm1.Button2Click(Sender: TObject);
var sDateTime:string;
DateTime:TDateTime;
SystemTime: TSystemTime;
begin
DateSeparator:='-';
ShortDateFormat:='yyyy-MM-dd';
LongDateFormat:='yyyy''年'',MM''月'',dd''日''';
TimeSeparator:=':';
sDateTime:=IdDayTime1.DayTimeStr;
sDateTime:=CopyDateTime(sDateTime);
Edit4.Text:=sDateTime;
DateTime:=StrToDateTime(SDateTime); // 获得时间(TDateTime格式)
DateTimeToSystemTime(DateTime,systemtime); // TDateTime格式转化TSystemTime
SetLocalTime(SystemTime); // 设置系统时间
GetLocalTime(SystemTime); // 读取系统时间
DateTime:=SystemTimeToDateTime(systemtime); // TSystemTime格式转化TDateTime
Edit5.Text:=DateTimetoStr(DateTime);
end;
procedure TForm1.Timer1Timer(Sender: TObject); // 定时同步
var sDateTime:string;
DateTime:TDateTime;
SystemTime: TSystemTime;
begin
sDateTime:=IdDayTime1.DayTimeStr;
sDateTime:=CopyDateTime(sDateTime);
DateTime:=StrToDateTime(SDateTime); // 获得时间(TDateTime格式)
DateTimeToSystemTime(DateTime,systemtime); // TDateTime格式转化TSystemTime格式
SetLocalTime(SystemTime); // 设置系统时间
StatusBar1.Panels[1].Text:='校正时间:'+sDateTime;
end;
procedure TForm1.CheckBox1Click(Sender: TObject);
begin
if CheckBox1.Checked then
begin
Button1Click(Sender);
Timer1.Enabled:=True;
end
else
Timer1.Enabled:=False;
end;