【问题标题】:Is there an Indy server property equivalent to TCustomWinSocket.Data?是否有与 TCustomWinSocket.Data 等效的 Indy 服务器属性?
【发布时间】:2015-10-16 14:50:00
【问题描述】:

当我使用 TServerSocket 时,我可以使用属性 Data 来存储指向类的指针,例如为每个客户端。

现在我将使用 Indy TIdCmdTCPServer,我想知道是否有等效的属性。

【问题讨论】:

    标签: sockets delphi indy indy10


    【解决方案1】:

    是的,有 - TIdContext.Data 属性。在为您提供TIdCommand 参数而不是TIdContext 参数的TIdCmdTCPServer 事件中,您可以从TIdCommand.Context 属性访问TIdContext 对象。例如:

    type
      TMyClass = class
        // add whatever you need...
      end;
    
    procedure TForm1.IdCmdTCPServer1Connect(AContext: TIdContext);
    var
      MyCls: TMyClass;
    begin
      MyCls := TMyClass.Create;
      // initialize MyCls as needed...
      AContext.Data := MyCls;
    end;
    
    procedure TForm1.IdCmdTCPServer1Disconnect(AContext: TIdContext);
    begin
      AContext.Data.Free;
      AContext.Data := nil;
    end;
    
    procedure TForm1.IdCmdTCPServer1CommandHandlerCommand(ACommand: TIdCommand);
    var
      MyCls: TMyClass;
    begin
      MyCls := TMyClass(ACommand.Context.Data);
      // use MyCls as needed...
    end;
    

    Indy 还有另一个有用的功能。您可以从TIdServerContext 派生一个自定义类,添加您想要的任何内容,然后在激活服务器之前将其分配给服务器的ContextClass 属性。这样,当您需要访问自定义成员时,您可以简单地将任何 TIdContext 指针类型转换为您的类类型。例如:

    type
      TMyContext = class(TIdServerContext)
      public
        // add whatever you need...
        constructor Create(AConnection: TIdTCPConnection; AYarn: TIdYarn; AList: TIdContextThreadList = nil); override;
        destructor Destroy; override;
      end;
    
    constructor TMyContext.Create(AConnection: TIdTCPConnection; AYarn: TIdYarn; AList: TIdContextThreadList = nil);
    begin
      inherited;
      //...
    end;
    
    destructor TMyContext.Destroy;
    begin
      //...
      inherited;
    end;
    
    procedure TForm1.FormCreate(Sender: TObject);
    begin
      IdCmdTCPServer1.ContextsClass := TMyContext;
    end;
    
    procedure TForm1.IdCmdTCPServer1Connect(AContext: TIdContext);
    var
      MyCtx: TMyContext;
    begin
      MyCtx := TMyClass(AContext);
      // initialize MyCtx as needed...
    end;
    
    procedure TForm1.IdCmdTCPServer1CommandHandlerCommand(ACommand: TIdCommand);
    var
      MyCtx: TMyContext;
    begin
      MyCtx := TMyClass(ACommand.Context);
      // use MyCtx as needed...
    end;
    

    这样,当您可以使用服务器已经为您创建的类时,您无需浪费时间和内存为每个客户端分配单独的类。

    【讨论】:

    • 你说:“你不需要浪费时间和内存为每个客户端分配一个单独的类”。这对我来说是一个新的范式,我不明白。我不想利用你的意愿,虽然我现在正在这样做,但是......你有例子吗?
    • 我添加了一些例子。
    • Remy,基于第一个示例,如何在 TIdCmdTCPServer 生成的事件之外访问我的类?例如,在 TSocketServer 中,我使用SocketServer1.Socket.Connections[number_of_connection].data。 TIdCmdTCPServer 中的等价物是什么?
    • 您真的不应该访问服务器事件之外的连接。但如果你必须:List := IdCmdTCPServer1.Contexts.LockList; try MyCls := TMyClass(TIdContext(List[index]).Data); {use MyCls as needed} finally IdCmdTCPServer1.Contexts.UnlockList end;
    • 我描述的是如何使用 Indy 来实现。您的 App 命令处理程序必须锁定 Contexts 列表,遍历列表以寻找合适的客户端,向其发送数据,然后解锁列表。
    猜你喜欢
    • 2017-02-16
    • 2014-05-28
    • 2018-10-25
    • 2011-02-19
    • 1970-01-01
    • 2014-09-29
    • 1970-01-01
    • 2019-10-12
    • 1970-01-01
    相关资源
    最近更新 更多