GroupMonitor.pas 5.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250
  1. unit GroupMonitor;
  2. interface
  3. uses
  4. Windows, SysUtils, Classes, GroupWebSocket, GroupClient;
  5. type
  6. TGroupHeartbeatThread = class;
  7. TGroupKeepAlive = class;
  8. TGroupMonitor = class
  9. private
  10. FLastTime: DWORD;
  11. FGroupHeartbeat: TGroupHeartbeatThread;
  12. FGroupKeepAlive: TGroupKeepAlive;
  13. FLock: TRTLCriticalSection;
  14. FClient: TGroupClient;
  15. FRunning: Boolean;
  16. FPingInterval: Integer;
  17. FPingTimeout: Integer;
  18. FKeepAlive: Boolean;
  19. procedure SetRunning(const Value: Boolean);
  20. procedure SetKeepAlive(const Value: Boolean);
  21. class function GetMonitor: TGroupMonitor;
  22. public
  23. constructor Create;
  24. destructor Destroy; override;
  25. procedure Start(AClient: TGroupClient);
  26. procedure Stop;
  27. procedure ReflashLastTime;
  28. property Running: Boolean read FRunning write SetRunning;
  29. //"pingInterval":25000,"pingTimeout":60000
  30. property PingInterval: Integer read FPingInterval write FPingInterval;
  31. property PingTimeout: Integer read FPingTimeout write FPingTimeout;
  32. property KeepAlive: Boolean read FKeepAlive write SetKeepAlive;
  33. end;
  34. TGroupHeartbeatThread = class(TThread)
  35. private
  36. FGroupMonitor: TGroupMonitor;
  37. public
  38. constructor Create(AGroupMonitor: TGroupMonitor);
  39. procedure Execute; override;
  40. end;
  41. TGroupKeepAlive = class(TThread)
  42. private
  43. FGroupMonitor: TGroupMonitor;
  44. public
  45. constructor Create(AGroupMonitor: TGroupMonitor);
  46. procedure Execute; override;
  47. end;
  48. {
  49. TGroupMonitor
  50. 一、监控心跳
  51. 1.管理TGroupClient的心跳(发送和接收心跳);
  52. 2.可以设置心跳间隔时间;
  53. 3.设置心跳超时时间;
  54. 4.超时重连机制;
  55. 二、监控处理GroupClient异常断开
  56. 1、异常重连
  57. 三、同步与主服务的连接状态
  58. }
  59. implementation
  60. uses
  61. LoggerImport, DateUtils;
  62. //var
  63. // GrpMonitor: TGroupMonitor;
  64. { TGroupMonitor }
  65. constructor TGroupMonitor.Create;
  66. begin
  67. inherited;
  68. FPingInterval := 25000;
  69. FPingTimeout := 60000;
  70. InitializeCriticalSection(FLock);
  71. FRunning := False;
  72. end;
  73. destructor TGroupMonitor.Destroy;
  74. begin
  75. Stop;
  76. DeleteCriticalSection(FLock);
  77. inherited;
  78. end;
  79. class function TGroupMonitor.GetMonitor: TGroupMonitor;
  80. begin
  81. // if GrpMonitor = nil then
  82. // GrpMonitor := TGroupMonitor.Create;
  83. // Result := GrpMonitor;
  84. end;
  85. procedure TGroupMonitor.ReflashLastTime;
  86. begin
  87. EnterCriticalSection(FLock);
  88. FLastTime := GetTickCount;
  89. LeaveCriticalSection(FLock);
  90. end;
  91. procedure TGroupMonitor.SetKeepAlive(const Value: Boolean);
  92. begin
  93. if FKeepAlive = Value then
  94. Exit;
  95. FKeepAlive := Value;
  96. if FKeepAlive then
  97. begin
  98. if FGroupKeepAlive <> nil then
  99. begin
  100. FGroupKeepAlive.Terminate;
  101. FGroupKeepAlive.WaitFor;
  102. FGroupKeepAlive := nil;
  103. end;
  104. FGroupKeepAlive := TGroupKeepAlive.Create(Self);
  105. FGroupKeepAlive.Resume;
  106. end
  107. else
  108. begin
  109. if FGroupKeepAlive <> nil then
  110. begin
  111. FGroupKeepAlive.Terminate;
  112. FGroupKeepAlive.WaitFor;
  113. FGroupKeepAlive := nil;
  114. end;
  115. end;
  116. end;
  117. procedure TGroupMonitor.SetRunning(const Value: Boolean);
  118. begin
  119. FRunning := Value;
  120. end;
  121. procedure TGroupMonitor.Start(AClient: TGroupClient);
  122. begin
  123. ReflashLastTime;
  124. if AClient = nil then
  125. Exit;
  126. if FRunning then
  127. Exit;
  128. Stop;
  129. FClient := AClient;
  130. FGroupHeartbeat := TGroupHeartbeatThread.Create(Self);
  131. FRunning := True;
  132. end;
  133. procedure TGroupMonitor.Stop;
  134. begin
  135. if not FRunning then
  136. Exit;
  137. // FClient := nil;
  138. if Assigned(FGroupHeartbeat) then
  139. begin
  140. FGroupHeartbeat.Terminate;
  141. try
  142. FGroupHeartbeat.WaitFor
  143. finally
  144. FGroupHeartbeat := nil;
  145. end;
  146. end;
  147. FRunning := False;
  148. end;
  149. //EnterCriticalSection(LastTimeLock); {开始: 轮到我了其他线程走开}
  150. //LeaveCriticalSection(LastTimeLock); {结束: 其他线程可以来了}
  151. { TMonitorThread }
  152. constructor TGroupHeartBeatThread.Create(AGroupMonitor: TGroupMonitor);
  153. begin
  154. FGroupMonitor := AGroupMonitor;
  155. inherited Create(False);
  156. end;
  157. procedure TGroupHeartBeatThread.Execute;
  158. var
  159. AIntervalTime: DWORD;
  160. iLoop: Integer;
  161. begin
  162. while not Terminated do
  163. begin
  164. AIntervalTime := GetTickCount - FGroupMonitor.FLastTime;
  165. if AIntervalTime > FGroupMonitor.FPingTimeout then
  166. begin
  167. Error(IntToStr(FGroupMonitor.FPingTimeout div 1000) +
  168. '60秒内没有收到服务端消息,启动重联.', 'TGroupHeartBeatThread.Execute');
  169. // MainForm.TimerForreconnectgroup.Enabled := False;
  170. // MainForm.TimerForreconnectgroup.Enabled := True;
  171. Exit;
  172. end;
  173. if AIntervalTime > FGroupMonitor.FPingInterval then
  174. begin
  175. FGroupMonitor.FClient.Ping;
  176. end;
  177. for iLoop := 0 to 19 do
  178. begin
  179. if Terminated then
  180. Exit;
  181. Sleep(1000);
  182. end;
  183. end;
  184. end;
  185. { TGroupKeepAlive }
  186. constructor TGroupKeepAlive.Create(AGroupMonitor: TGroupMonitor);
  187. begin
  188. FGroupMonitor := AGroupMonitor;
  189. inherited Create(True);
  190. end;
  191. procedure TGroupKeepAlive.Execute;
  192. var
  193. AIntervalTime: DWORD;
  194. iLoop: Integer;
  195. begin
  196. while not Terminated do
  197. begin
  198. AIntervalTime := Random(10) + 10;
  199. for iLoop := 0 to AIntervalTime - 1 do
  200. begin
  201. if Terminated then
  202. Exit;
  203. Sleep(1000);
  204. end;
  205. if not FGroupMonitor.FClient.Connected then
  206. FGroupMonitor.FClient.Connect;
  207. end;
  208. end;
  209. initialization
  210. finalization
  211. end.