How to track number of clients with Indy TIdTCPServer

后端 未结 4 492
Happy的楠姐
Happy的楠姐 2021-01-03 07:37

I want to know the number of current client connections to an Indy 9 TIdTCPServer (on Delphi 2007)

I can\'t seem to find a property that gives this.

I\'ve tr

4条回答
  •  悲哀的现实
    2021-01-03 08:18

    Not sure why using OnConnect and OnDisconnect wouldn't work for you, but what we have done is to create a descendant of TIdCustomTCPServer; to override its DoConnect and DoDisconnect methods and create and use our own descendant of TIdServerContext (a thread descendant that will "serve" a connection).

    You make the TIdCustomTCPServer aware of your own TIdServerContext class by:

    (Edit Added conditional defines to show how to make it work for Indy9)

    type
    // Conditional defines so that we can use the same ancestors as in Indy10 and we
    // can use the same method signatures for DoConnect and DoDisconnect regardless 
    // of the Indy version. Add other conditional defines as needed.
    // Note: for INDY9 to be defined, you need to include the appropriate includes 
    // from Indy, or define it in your own include file.
    {$IFDEF INDY9}  
      TIdContext = TIdPeerThread;
      TIdServerContext = TIdContext;
      TIdCustomTCPServer = TIdTCPServer;
    {$ENDIF}
    
      TOurContext = class(TIdServerContext)
      private
        FConnectionId: cardinal;
      public
        property ConnectionId: cardinal ...;
      end;
    
    ...
    
    constructor TOurServer.Create(aOwner: TComponent);
    begin
      inherited Create(aOwner);
    
      ...
      {$IFDEF INDY10_UP}
        ContextClass := TOurContext;
      {$ELSE}
        ThreadClass := TOurContext;
      {$ENDIF}
      ...
    end;
    

    In the DoConnect override of our TIdCustomTCPServer descendant we set the ConnectionID of our context class to a unique value:

    procedure TOurServer.DoConnect(AContext: TIdContext);
    var
      OurContext: TOurContextabsolute AContext;
    begin
      Assert(AContext is TOurContext);
      HandleGetNewConnectionID(OurContext, OurContext.FConnectionID);
    
      inherited DoConnect(AContext);
    
      ...
    
    end;
    

    Our DoDisconnect override clears the ConnectionID:

    procedure TOurServer.DoDisconnect(AContext: TIdContext);
    var
      OurContext: TOurContextabsolute AContext;
    begin
      Assert(AContext is TOurContext);
      OurContext.FConnectionID := 0;
    
      ...
    
      inherited DoDisconnect(AContext);
    end;
    

    Now it is possible to get a count of the current connections at any time:

    function TOurServer.GetConnectionCount: Integer;
    var
      i: Integer;
      CurrentContext: TOurContext;
      ContextsList: TList;
    begin
      MyLock.BeginRead;
      try
        Result := 0;
    
        if not Assigned(Contexts) then
          Exit;
    
        ContextsList := Contexts.LockList;
        try
    
          for i := 0 to ContextsList.Count - 1 do
          begin
            CurrentContext := ContextsList[i] as TOurContext;
    
            if CurrentContext.ConnectionID > 0 then
              Inc(Result);
          end;
    
        finally
          Contexts.UnLockList;
        end;
      finally
        MyLock.EndRead;
      end;
    end;
    

提交回复
热议问题