| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250 |
- unit GroupMonitor;
- interface
- uses
- Windows, SysUtils, Classes, GroupWebSocket, GroupClient;
- type
- TGroupHeartbeatThread = class;
- TGroupKeepAlive = class;
-
- TGroupMonitor = class
- private
- FLastTime: DWORD;
- FGroupHeartbeat: TGroupHeartbeatThread;
- FGroupKeepAlive: TGroupKeepAlive;
- FLock: TRTLCriticalSection;
- FClient: TGroupClient;
- FRunning: Boolean;
- FPingInterval: Integer;
- FPingTimeout: Integer;
- FKeepAlive: Boolean;
- procedure SetRunning(const Value: Boolean);
- procedure SetKeepAlive(const Value: Boolean);
- class function GetMonitor: TGroupMonitor;
- public
- constructor Create;
- destructor Destroy; override;
- procedure Start(AClient: TGroupClient);
- procedure Stop;
- procedure ReflashLastTime;
- property Running: Boolean read FRunning write SetRunning;
- //"pingInterval":25000,"pingTimeout":60000
- property PingInterval: Integer read FPingInterval write FPingInterval;
- property PingTimeout: Integer read FPingTimeout write FPingTimeout;
- property KeepAlive: Boolean read FKeepAlive write SetKeepAlive;
- end;
- TGroupHeartbeatThread = class(TThread)
- private
- FGroupMonitor: TGroupMonitor;
- public
- constructor Create(AGroupMonitor: TGroupMonitor);
- procedure Execute; override;
- end;
- TGroupKeepAlive = class(TThread)
- private
- FGroupMonitor: TGroupMonitor;
- public
- constructor Create(AGroupMonitor: TGroupMonitor);
- procedure Execute; override;
- end;
- {
- TGroupMonitor
- 一、监控心跳
- 1.管理TGroupClient的心跳(发送和接收心跳);
- 2.可以设置心跳间隔时间;
- 3.设置心跳超时时间;
- 4.超时重连机制;
- 二、监控处理GroupClient异常断开
- 1、异常重连
- 三、同步与主服务的连接状态
- }
- implementation
- uses
- LoggerImport, DateUtils;
- //var
- // GrpMonitor: TGroupMonitor;
- { TGroupMonitor }
- constructor TGroupMonitor.Create;
- begin
- inherited;
- FPingInterval := 25000;
- FPingTimeout := 60000;
- InitializeCriticalSection(FLock);
- FRunning := False;
- end;
- destructor TGroupMonitor.Destroy;
- begin
- Stop;
- DeleteCriticalSection(FLock);
- inherited;
- end;
- class function TGroupMonitor.GetMonitor: TGroupMonitor;
- begin
- // if GrpMonitor = nil then
- // GrpMonitor := TGroupMonitor.Create;
- // Result := GrpMonitor;
- end;
- procedure TGroupMonitor.ReflashLastTime;
- begin
- EnterCriticalSection(FLock);
- FLastTime := GetTickCount;
- LeaveCriticalSection(FLock);
- end;
- procedure TGroupMonitor.SetKeepAlive(const Value: Boolean);
- begin
- if FKeepAlive = Value then
- Exit;
- FKeepAlive := Value;
- if FKeepAlive then
- begin
- if FGroupKeepAlive <> nil then
- begin
- FGroupKeepAlive.Terminate;
- FGroupKeepAlive.WaitFor;
- FGroupKeepAlive := nil;
- end;
- FGroupKeepAlive := TGroupKeepAlive.Create(Self);
- FGroupKeepAlive.Resume;
- end
- else
- begin
- if FGroupKeepAlive <> nil then
- begin
- FGroupKeepAlive.Terminate;
- FGroupKeepAlive.WaitFor;
- FGroupKeepAlive := nil;
- end;
- end;
- end;
- procedure TGroupMonitor.SetRunning(const Value: Boolean);
- begin
- FRunning := Value;
- end;
- procedure TGroupMonitor.Start(AClient: TGroupClient);
- begin
- ReflashLastTime;
- if AClient = nil then
- Exit;
- if FRunning then
- Exit;
- Stop;
- FClient := AClient;
- FGroupHeartbeat := TGroupHeartbeatThread.Create(Self);
- FRunning := True;
- end;
- procedure TGroupMonitor.Stop;
- begin
- if not FRunning then
- Exit;
- // FClient := nil;
- if Assigned(FGroupHeartbeat) then
- begin
- FGroupHeartbeat.Terminate;
- try
- FGroupHeartbeat.WaitFor
- finally
- FGroupHeartbeat := nil;
- end;
- end;
- FRunning := False;
- end;
- //EnterCriticalSection(LastTimeLock); {开始: 轮到我了其他线程走开}
- //LeaveCriticalSection(LastTimeLock); {结束: 其他线程可以来了}
- { TMonitorThread }
- constructor TGroupHeartBeatThread.Create(AGroupMonitor: TGroupMonitor);
- begin
- FGroupMonitor := AGroupMonitor;
- inherited Create(False);
- end;
- procedure TGroupHeartBeatThread.Execute;
- var
- AIntervalTime: DWORD;
- iLoop: Integer;
- begin
- while not Terminated do
- begin
- AIntervalTime := GetTickCount - FGroupMonitor.FLastTime;
- if AIntervalTime > FGroupMonitor.FPingTimeout then
- begin
- Error(IntToStr(FGroupMonitor.FPingTimeout div 1000) +
- '60秒内没有收到服务端消息,启动重联.', 'TGroupHeartBeatThread.Execute');
- // MainForm.TimerForreconnectgroup.Enabled := False;
- // MainForm.TimerForreconnectgroup.Enabled := True;
- Exit;
- end;
- if AIntervalTime > FGroupMonitor.FPingInterval then
- begin
- FGroupMonitor.FClient.Ping;
- end;
- for iLoop := 0 to 19 do
- begin
- if Terminated then
- Exit;
- Sleep(1000);
- end;
- end;
- end;
- { TGroupKeepAlive }
- constructor TGroupKeepAlive.Create(AGroupMonitor: TGroupMonitor);
- begin
- FGroupMonitor := AGroupMonitor;
- inherited Create(True);
- end;
- procedure TGroupKeepAlive.Execute;
- var
- AIntervalTime: DWORD;
- iLoop: Integer;
- begin
- while not Terminated do
- begin
- AIntervalTime := Random(10) + 10;
- for iLoop := 0 to AIntervalTime - 1 do
- begin
- if Terminated then
- Exit;
- Sleep(1000);
- end;
- if not FGroupMonitor.FClient.Connected then
- FGroupMonitor.FClient.Connect;
- end;
- end;
- initialization
- finalization
- end.
|