[Delphi] Передача параметра функции

Discussion in 'С/С++, C#, Rust, Swift, Go, Java, Perl, Ruby' started by dreamcation, 19 Jul 2010.

  1. dreamcation

    dreamcation New Member

    Joined:
    2 Apr 2010
    Messages:
    75
    Likes Received:
    0
    Reputations:
    0
    Здравствуйте. Имеется код:

    Code:
    procedure TForm1.OnAuthTimer(Sender: TObject);
    begin
      
    end;
    
    procedure TForm1.ServerClientConnect(Sender: TObject; Socket: TCustomWinSocket);
    begin
      Timer := TTimer.Create(Form1);
      Timer.Interval := 5000;
      Timer.OnTimer := OnAuthTimer;
    end;
    
    Суть его такова: при подключении клиента к серверу создается таймер с событием OnAuthTimer. По истечении определенного времени таймер должен разрывать соединения с теми клиентами от которых не пришли данные для авторизации.

    Вопрос. Как процедуре OnAuthTimer передать Socket из процедуры ServerClientConnect, что бы таймер мог отключить клиента?
     
  2. ADR-007

    ADR-007 Member

    Joined:
    12 Jul 2010
    Messages:
    218
    Likes Received:
    9
    Reputations:
    0
    создай объект наследник таймера
    найди в TTimer процедуру в которые осуществляется вызов OnTimer. Предположим что называется TimerProc тогда можно сделать то так:

    Code:
    TMyTimer = class(TTimer)
    	private		
    		fMySender : TObject 
    		fMyOnTimer : TProc<TObject> //delphi 2010 (procedure(Sender:TObject) of object в delphi 7)
    		procedure TimerProc;
    	published
    		property MyOnTimer write fMyOnTimer;
    		Property MySender	write fMySender;
    	end;
    ...
    
    ...
    procedure MyTimer.TimerProc;
    begin
    	//копирайт TimerProc
    	If assigned(fMyOnSender) then fMyOntimer(fMySender);
    end;
    ...
    
    
    
    procedure TForm1.ServerClientConnect(Sender: TObject; Socket: TCustomWinSocket);
    begin
      Timer := TMyTimer.Create(Form1);
      Timer.Interval := 5000;
    	Timer.MySender := Sender;
      Timer.MyOnTimer := OnAuthTimer;
    end;
    проверить не имею возможности ...
     
    #2 ADR-007, 19 Jul 2010
    Last edited: 19 Jul 2010
  3. ADR-007

    ADR-007 Member

    Joined:
    12 Jul 2010
    Messages:
    218
    Likes Received:
    9
    Reputations:
    0
    или просто
    Code:
    TMyTimer = class(TTimer)
      MySender:Tobject;
    end;
    
    procedure TForm1.OnAuthTimer(Sender: TObject);
    begin
      Timer.MySender................
    end;
    
    procedure TForm1.ServerClientConnect(Sender: TObject; Socket: TCustomWinSocket);
    begin
      Timer := TMyTimer.Create(Form1);
      Timer.Interval := 5000;
      Timer.Mysender:=sender; ///<<<<<<<<<<<<<<
      Timer.OnTimer := OnAuthTimer;
    end;
    
    и при таймере читай MySender ...
     
    #3 ADR-007, 19 Jul 2010
    Last edited: 19 Jul 2010
  4. dreamcation

    dreamcation New Member

    Joined:
    2 Apr 2010
    Messages:
    75
    Likes Received:
    0
    Reputations:
    0
    Спасибо, но мне это кажется слишком сложным) а что если сделать так:

    Code:
    procedure TForm1.OnAuthTimer(Sender: TObject; Socket: TCustomWinSocket);
    begin
      
    end;
    
    procedure TForm1.ServerClientConnect(Sender: TObject; Socket: TCustomWinSocket);
    begin
      Timer := TTimer.Create(Form1);
      Timer.Interval := 5000;
      Timer.OnTimer := OnAuthTimer([B][что сюда передать?][/B],Socket);
    end;
    что надо передать в функцию что бы это работало? и вообще можно ли так делать?)
     
  5. Chrome~

    Chrome~ Elder - Старейшина

    Joined:
    13 Dec 2008
    Messages:
    937
    Likes Received:
    162
    Reputations:
    27
    По идеи можно так реализовать. Только нужно сделать класс наследник от TTimer.
     
  6. ADR-007

    ADR-007 Member

    Joined:
    12 Jul 2010
    Messages:
    218
    Likes Received:
    9
    Reputations:
    0
    так как ты написал делать нельзя ...
    свойство Timer.OnTimer это лишь указатель на процедуру, а ты хочешь передать ему параметры) да еще и не совместимы
     
  7. ADR-007

    ADR-007 Member

    Joined:
    12 Jul 2010
    Messages:
    218
    Likes Received:
    9
    Reputations:
    0
    я об этом и написал выше ...
     
    1 person likes this.
  8. dreamcation

    dreamcation New Member

    Joined:
    2 Apr 2010
    Messages:
    75
    Likes Received:
    0
    Reputations:
    0
    пробую сделать предложенным вариантом. все ок, но я не понял последнего шага, куда, например, мне необходимо записать действия которые будут выполняться по таймеру? например:
    Code:
    Socket.Disconnect(0);
    что бы отключить клиента.
     
  9. ADR-007

    ADR-007 Member

    Joined:
    12 Jul 2010
    Messages:
    218
    Likes Received:
    9
    Reputations:
    0
    Code:
    procedure TForm1.OnAuthTimer(Sender: TObject);
    begin
      <Имя об’єкта>(Timer.MySender).disconect;
     // напр если бы это был TMemo то TMemo(Timer.MySender).text:='ffff';
    //<Название объекта>(<указатель на объект>).<методы объекта>
    end;
    
    procedure TForm1.ServerClientConnect(Sender: TObject; Socket: TCustomWinSocket);
    begin
      Timer := TMyTimer.Create(Form1);
      Timer.Interval := 5000;
      Timer.Mysender:=sender; ///<<<<<<<<<<<<<<
      Timer.OnTimer := OnAuthTimer;
    end;
    какие методы и какого объекта нужно выполнить?
     
  10. dreamcation

    dreamcation New Member

    Joined:
    2 Apr 2010
    Messages:
    75
    Likes Received:
    0
    Reputations:
    0
    нужно выполнить ServerSocket1.Socket.Disconnect(i); // i - номер клиента
    я так понимаю ServerSocket1.Socket это объект, а Disconnect(0) это метод...)
     
  11. ADR-007

    ADR-007 Member

    Joined:
    12 Jul 2010
    Messages:
    218
    Likes Received:
    9
    Reputations:
    0
    Code:
    procedure TForm1.OnAuthTimer(Sender: TObject);
    begin
      TServerSocket(Timer.MySender).Socket.Disconnect; //що за і ???
    
    end;
    
    procedure TForm1.ServerClientConnect(Sender: TObject; Socket: TCustomWinSocket);
    begin
      Timer := TMyTimer.Create(Form1);
      Timer.Interval := 5000;
      Timer.Mysender:=sender; ///<<<<<<<<<<<<<<
      Timer.OnTimer := OnAuthTimer;
    end;
    для чего 'i'? это действительно такое есть (. disconect (i)) или ты приписал?
    если нет то как ты создаешь несколько клиентов??

    для чего указатель ServerSocket1? ты накинул компонент на форму??

    ПС ServerSocket1 - это указатель на объект TServerSocket
    а все что после точки (ServerSocket1. *) - это методы или свойства объекта
    (Процедуры объекта называют его методами а то что объявлено как
    `Property MyProperty write SetProperty read GetProperty это свойства '(свойства можно задавать либо читать))

    сейчас посмотрим как переведет гугл то что я написал))
     
    #11 ADR-007, 19 Jul 2010
    Last edited: 19 Jul 2010
  12. dreamcation

    dreamcation New Member

    Joined:
    2 Apr 2010
    Messages:
    75
    Likes Received:
    0
    Reputations:
    0
    Спасибо за развернутый ответ.
    i - это номер клиента. я отключаю конкретного клиента который не прошел авторизацию в течение 5 секунд.

    У меня возникла еще одна идея реализации данной функции...
    Можно ли к динамически создаваемому таймеру прикрепить дополнительное свойство в котором будет хранится к примеру IP адрес клиента? Тогда можно было бы просто создать таймер, указать ему в свойстве IP. По истечении времени таймер уничтожает сам себя, и смотрит в специальный список, в котором IP адреса авторизовавшихся клиентов, и если не находит того IP который прописан в его свойстве то дает серверу команду отключить его.
    Мне кажется этот метод хорош тем что нет необходимости следить за каждым таймеро посредством поля Tag. Просто при работе сервера одновременно будут создаваться десятки таких таймеров одновременно.
     
  13. ADR-007

    ADR-007 Member

    Joined:
    12 Jul 2010
    Messages:
    218
    Likes Received:
    9
    Reputations:
    0
    значит ServerSocket1 не должен быть динамичным. тогда так:
    Code:
    TMyTimer = class(TTimer)
      i:integer;
    	IP:string;
    
    	//пиши тут що ще треба напр Port:integer;
    end;
    
    procedure TForm1.OnAuthTimer(Sender: TObject);
    begin
      ServerSocket1.Socket.Disconnect(i);
    end;
    
    procedure TForm1.ServerClientConnect(Sender: TObject; Socket: TCustomWinSocket);
    begin
      Timer := TMyTimer.Create(Form1);
      Timer.Interval := 5000;
      Timer.i:=// i:=???
    	Timer.IP:=//IP:=???
    	Timer.OnTimer := OnAuthTimer;
    end;
    АЛЕ так задавати властивості в такий спосіб не рекомендується!
    (правильно так:
    Code:
    TMyTimer = class(TTimer)
    	private
      	fi:integer;
    		fIP:string;
    	published
    [B]		property I:integer write fi read fi;
    		property IP:string write fIP read fIP;[/B]
    end;
    )
    но в данном случае это не важно так как ты все равно не используешь переменные внутри объекта.
     
  14. dreamcation

    dreamcation New Member

    Joined:
    2 Apr 2010
    Messages:
    75
    Likes Received:
    0
    Reputations:
    0
    не много ошибся. конкретный клиент отключается таким образом:
    Code:
    Server.Socket.Connections[I].Disconnect(0);
     
  15. ADR-007

    ADR-007 Member

    Joined:
    12 Jul 2010
    Messages:
    218
    Likes Received:
    9
    Reputations:
    0
    Code:
    TMyTimer = class(TTimer)
      i:integer;
    	IP:string;
    
    	//пиши тут що ще треба напр Port:integer;
    end;
    
    procedure TForm1.OnAuthTimer(Sender: TObject);
    begin
    [b]  Server.Socket.Connections[I].Disconnect(0);[/b] //<<<<<<<<<<<<
    end;
    
    procedure TForm1.ServerClientConnect(Sender: TObject; Socket: TCustomWinSocket);
    begin
      Timer := TMyTimer.Create(Form1);
      Timer.Interval := 5000;
      Timer.i:=// i:=???
      Timer.IP:=//IP:=???
      Timer.OnTimer := OnAuthTimer;
    end;
    могу написать класс (объект) чтобы не надо было создавать процедуры и т.д. а просто
    TObjectName.Create (ip, i, sender) и все
    PS ти розумієш українську? схарився перекладати)
     
    #15 ADR-007, 19 Jul 2010
    Last edited: 19 Jul 2010
  16. dreamcation

    dreamcation New Member

    Joined:
    2 Apr 2010
    Messages:
    75
    Likes Received:
    0
    Reputations:
    0
    да, буду весьма признателен за класс. Українську розумію нормально))
    в классе достаточно будет параметра IP, т.к. удаление клиента будет производится таким образом
    Code:
    procedure TForm1.OnAuthTimer(Sender: TObject);
    var
      i: integer;
    begin
      for i := 0 to Server.Socket.ActiveConnections - 1 do
        if Server.Socket.Connections[i].RemoteAddress = IP then
        begin
          Server.Socket.Connections[i].Destroy;
          Exit;
        end;
      Sender.Free; // После одного цикла таймер должен уничтожиться
    end;
    главное необходимо сделать так что бы когда например будет создано 20 таймеров они не мешали друг другу) т.е. каждый работает независимо от друго...
     
    #16 dreamcation, 19 Jul 2010
    Last edited: 19 Jul 2010
  17. ADR-007

    ADR-007 Member

    Joined:
    12 Jul 2010
    Messages:
    218
    Likes Received:
    9
    Reputations:
    0
    ось: (вибачай за затримку) )
    Code:
    type
      PServerSocket = ^TServerSocket; //можливо цього і [B]не[/B] треба
    
      { TTimerConnect }
    
      TTimerConnect = class
        private
          FTimer:TTimer;
          FIP:string;
          FServer:PServerSocket;
          procedure fOnTimer(Sender:TObject);
        public
          constructor GoTimer(const IP:string; ServerSocket:TServerSocket);
          destructor  destroy;
      end;
    
    implementation
    
    { TTimerConnect }
    
    procedure TTimerConnect.fOnTimer(Sender: TObject);
    var
      i:integer;
    begin
      for i := 0 to FServer.Socket.ActiveConnections - 1 do
        if FServer.Socket.Connections[i].RemoteAddress = FIP then
        begin
          FServer.Socket.Connections[i].Destroy;
          Break;                //потрібно вийти з циклу а не з процедури!
        end;
      self.destroy;               
    end;
    
    constructor TTimerConnect.GoTimer(const IP: string; ServerSocket: PServerSocket
      );
    begin
      inherited Create;
      FIP     :=  ip;
      FServer :=  ServerSocket;
      FTimer  :=  TTimer.create(nil);
      FTimer.interval:=5000;
      FTimer.OnTimer:=fOnTimer;
      //не пам’ятаю можливо ще щось потрібно зробити щоб запустити таймер
    end;
    
    destructor TTimerConnect.destroy;
    begin
      FTimer.Free;
      inherited destroy;
    end;
    щось то дуже просто вийшло)
    запускаєш так
    TTimerConnect.GoTimer(Ip,server);// вказівник на цей об’єкт (timer:=TTimerConnect.GoTimer(Ip,server); ) не потрібно
    (метод Create виділяє пам’ять під об’єкт тобто кожний виклик цієї функції створює новий об’єкт)
    не маю можливості перевірити цей код...


    ПС а немає підсвідки синтаксису? типу
    Code:
    nil
     
    #17 ADR-007, 20 Jul 2010
    Last edited: 20 Jul 2010
  18. dreamcation

    dreamcation New Member

    Joined:
    2 Apr 2010
    Messages:
    75
    Likes Received:
    0
    Reputations:
    0
    ADR-007, все работает просто великолепно, именно так как надо. Очень благодарен вам за помощь!
     
  19. ADR-007

    ADR-007 Member

    Joined:
    12 Jul 2010
    Messages:
    218
    Likes Received:
    9
    Reputations:
    0
    завжди радий допомогти ;)