unit CorrespondService; interface uses ClientInfoService, Classes, IdTCPServer, EncryptService, SysUtils, SoftDogService, TypeUnit, Windows; type TThrdsType = (ttTerminate, ttNoDog); TScMonitor = class private FLinkCtrl: TLinkControl; FCriticalSection: TRTLCriticalSection; public constructor Create; destructor Destroy; override; procedure AddCount(AUser: Integer); procedure DeleteCount(AUser: Integer); function CanNotify(AUser: Integer): Boolean; procedure SetMaxLinks(const AV0Count, AV1Count, AV2Count: Integer); procedure InitCount; procedure NotifyClientInfo(AClientService: TClientInfoDM; AType: TOperType; APointer: Pointer = nil); procedure NotifyClientThreads(AClientThrds: TIdPeerThread; AType: TThrdsType); end; TScCorrespondService = class private FClientInfoService: TClientInfoDM; FIdTcpServer: TIdTcpServer; FMonitor: TScMonitor; FThrdsList: TThreadList; FPersistent: TScPersistent; {发送数据加密} FEncryptService: TScEncryptService; FSofeDog: TScSoftDog; function GetPort: Integer; procedure SetPort(const Value: Integer); procedure InitMethods; procedure ClearThrdsInfo; procedure AddClientThrdsInfo(AThread: TIdPeerThread; AInfo: PInfoRecd); procedure DeleteClientthrdsInfo(AThread: TIdPeerThread); procedure DoServerConnect(AThread: TIdPeerThread); procedure DoServerExecute(AThread: TIdPeerThread); procedure DoServerDisconnect(AThread: TIdPeerThread); procedure DoServerException(AThread: TIdPeerThread; AException: Exception); public constructor Create; destructor Destroy; override; function Open: Boolean; procedure CloseService; procedure DeleteClientThrds; procedure SetMaxLinks(const AV0Count, AV1Count, AV2Count: Integer); property Port: Integer read GetPort write SetPort; property SoftDog: TScSoftDog write FSofeDog; property ClientInfoService: TClientInfoDM read FClientInfoService write FClientInfoService; end; implementation { TScMonitor } procedure TScMonitor.AddCount(AUser: Integer); begin FLinkCtrl.AddCount(AUser); end; function TScMonitor.CanNotify(AUser: Integer): Boolean; begin Result := not FLinkCtrl.CheckIsFull(AUser); end; constructor TScMonitor.Create; begin FLinkCtrl := TLinkControl.Create; InitializeCriticalSection(FCriticalSection); end; procedure TScMonitor.DeleteCount(AUser: Integer); begin FLinkCtrl.DeleteCount(AUser); end; destructor TScMonitor.Destroy; begin FLinkCtrl.Free; DeleteCriticalSection(FCriticalSection); inherited; end; procedure TScMonitor.InitCount; begin FLinkCtrl.InitCount; end; procedure TScMonitor.NotifyClientInfo(AClientService: TClientInfoDM; AType: TOperType; APointer: Pointer); begin EnterCriticalSection(FCriticalSection); try AClientService.HandlerNotify(AType, APointer); finally LeaveCriticalSection(FCriticalSection); end; end; procedure TScMonitor.NotifyClientThreads(AClientThrds: TIdPeerThread; AType: TThrdsType); begin if AType = ttTerminate then begin AClientThrds.Connection.Disconnect; end; end; procedure TScMonitor.SetMaxLinks(const AV0Count, AV1Count, AV2Count: Integer); begin FLinkCtrl.V0MaxLinks := AV0Count; FLinkCtrl.V1MaxLinks := AV1Count; FLinkCtrl.V2MaxLinks := AV2Count; end; { TScCorrespondService } procedure TScCorrespondService.CloseService; {var I: Integer; thsList: TList; sText: string; thrds: TIdPeerThread; } begin if not FIdTcpServer.Active then Exit; { thsList := FIdTcpServer.Threads.LockList; try for I := thsList.Count - 1 downto 0 do begin thrds := TIdPeerThread(thsList.List^[I]); sText := FEncryptService.EncryptString('QUITOUT'); thrds.Connection.WriteLn(sText); end; finally FIdTcpServer.Threads.UnlockList; end; } FMonitor.InitCount; FMonitor.NotifyClientInfo(FClientInfoService, otDelete); ClearThrdsInfo; FIdTcpServer.Active := False; end; constructor TScCorrespondService.Create; begin FIdTcpServer := TIdTCPServer.Create(nil); FMonitor := TScMonitor.Create; FEncryptService := TScEncryptService.Create; FPersistent := TScPersistent.Create; FPersistent.ReadPersistentProperty; FThrdsList := TThreadList.Create; InitMethods; end; destructor TScCorrespondService.Destroy; begin CloseService; FIdTcpServer.Free; FMonitor.Free; FEncryptService.Free; FPersistent.WritePersistentProperty; FPersistent.Free; ClearThrdsInfo; FThrdsList.Free; inherited; end; function TScCorrespondService.GetPort: Integer; begin Result := FPersistent.Port; end; procedure TScCorrespondService.DoServerConnect(AThread: TIdPeerThread); begin end; procedure TScCorrespondService.DoServerDisconnect( AThread: TIdPeerThread); begin end; procedure TScCorrespondService.DoServerException(AThread: TIdPeerThread; AException: Exception); var I: Integer; ptThrds: PThrdsRecd; infoRec: PInfoRecd; lstThrds: TList; begin AThread.Connection.Disconnect; New(infoRec); lstThrds := FThrdsList.LockList; try for I := 0 to lstThrds.Count - 1 do begin ptThrds := lstThrds.List^[I]; if AThread = ptThrds.Thread then begin infoRec.IP := ptThrds.IP; infoRec.User := ptThrds.User; FMonitor.NotifyClientInfo(FClientInfoService, otDelete, infoRec); FMonitor.DeleteCount(infoRec.User); lstThrds.Delete(I); Dispose(ptThrds); Break; end; end; finally FThrdsList.UnlockList; Dispose(infoRec); end; end; procedure TScCorrespondService.DoServerExecute(AThread: TIdPeerThread); var infoRec: PInfoRecd; strText: string; begin if AThread.Connection.Server.Active and not AThread.Terminated then begin strText := AThread.Connection.ReadLn(#13#10, 1000, 100); New(infoRec); FEncryptService.DeEncryptString(strText, infoRec); if infoRec.Action = 0 then {链接} begin if FMonitor.CanNotify(infoRec.User) then begin FMonitor.NotifyClientInfo(FClientInfoService, otAdd, infoRec); strText := FEncryptService.EncryptString('SUCCESS'); AThread.Connection.WriteLn(strText); FMonitor.AddCount(infoRec.User); AddClientThrdsInfo(AThread, infoRec); end else begin strText := FEncryptService.EncryptString('ISFULL'); AThread.Connection.WriteLn(strText); end; end else if infoRec.Action = 1 then {断开} begin FMonitor.NotifyClientInfo(FClientInfoService, otDelete, infoRec); FMonitor.DeleteCount(infoRec.User); DeleteClientthrdsInfo(AThread); end else if infoRec.Action = 9 then {检测} begin strText := FSofeDog.ReadData(StrToInt(infoRec.IP), infoRec.User); strText := FEncryptService.EncryptString(strText); AThread.Connection.WriteLn(strText); FMonitor.NotifyClientInfo(FClientInfoService, otModify, infoRec); end; Dispose(infoRec); end; end; procedure TScCorrespondService.InitMethods; begin // FIdTcpServer.OnConnect := DoServerConnect; FIdTcpServer.OnExecute := DoServerExecute; // FIdTcpServer.OnDisconnect := DoServerDisconnect; FIdTcpServer.OnException := DoServerException; end; function TScCorrespondService.Open: Boolean; begin Result := True; if FIdTcpServer.Active then Exit; FIdTcpServer.Bindings.Clear; FIdTcpServer.Threads.Clear; FIdTcpServer.DefaultPort := Port; try FIdTcpServer.Active := True; except Result := False; end; end; procedure TScCorrespondService.SetPort(const Value: Integer); begin FPersistent.Port := Value; end; procedure TScCorrespondService.SetMaxLinks(const AV0Count, AV1Count, AV2Count: Integer); begin FMonitor.SetMaxLinks(AV0Count, AV1Count, AV2Count); end; procedure TScCorrespondService.DeleteClientThrds; var I, iUser: Integer; strIP: string; lstThrds: TList; thrds: PThrdsRecd; begin iuser := FClientInfoService.CurUser; strIP := FClientInfoService.CurIP; lstThrds := FThrdsList.LockList; try for I := 0 to lstThrds.Count - 1 do begin thrds := lstThrds.List^[I]; if SameText(thrds.IP, strIP) and (iUser = thrds.User) then begin if Assigned(thrds.Thread.Connection) then thrds.Thread.Connection.DisconnectSocket; FClientInfoService.DeleteCurRecord; FMonitor.DeleteCount(iUser); lstThrds.Delete(I); Dispose(thrds); Break; end; end; finally FThrdsList.UnlockList; end; end; procedure TScCorrespondService.AddClientThrdsInfo(AThread: TIdPeerThread; AInfo: PInfoRecd); var I: Integer; blFlag: Boolean; lstThrds: TList; ptThrds: PThrdsRecd; begin blFlag := False; lstThrds := FThrdsList.LockList; try for I := 0 to lstThrds.Count - 1 do begin ptThrds := lstThrds.List^[I]; if AThread = ptThrds.Thread then begin blFlag := True; Break; end; end; if not blFlag then begin New(ptThrds); ptThrds.Thread := AThread; ptThrds.IP := AInfo.IP; ptThrds.User := AInfo.User; lstThrds.Add(ptThrds); end; finally FThrdsList.UnlockList; end; end; procedure TScCorrespondService.DeleteClientthrdsInfo( AThread: TIdPeerThread); var I: Integer; lstThrds: TList; ptThrds: PThrdsRecd; begin lstThrds := FThrdsList.LockList; try for I := 0 to lstThrds.Count - 1 do begin ptThrds := lstThrds.List^[I]; if AThread = ptThrds.Thread then begin lstThrds.Delete(I); Dispose(ptThrds); Break; end; end; finally FThrdsList.UnlockList; end; end; procedure TScCorrespondService.ClearThrdsInfo; var I: Integer; lstThrds: TList; thrdsRec: PThrdsRecd; begin lstThrds := FThrdsList.LockList; try for I := 0 to lstThrds.Count - 1 do begin thrdsRec := lstThrds.List^[I]; Dispose(thrdsRec); end; finally FThrdsList.UnlockList; end; FThrdsList.Clear; end; end.