如何设置Indy自定义TIdIOHandler?

问题描述

我想为我的Indy TCP客户端使用自定义TIdioHandler,但我不知道如何设置它。我创建了一个新的IOHandler类,并在TIdioHandler.RegisterIOHandler中进行了注册,然后在我的新处理程序引用中使用了TIdTCPClient.CreateIOHandler。现在,当我尝试写入TIdTCPClient.socket时,出现“抽象错误”异常...除了示例之外,还需要配置其他内容吗?

  TIdEnhancedioHandler = class(TIdioHandlerSocket)
  public
    function AckNowledge(Command: Cardinal = 0): Boolean;
  end

{this is a client in a thread}
constructor TMyTCPClient.Create(const AHost: String; APort: Word);
begin
 inherited Create;
 FreeOnTerminate:= True;
 TIdEnhancedioHandler.RegisterIOHandler;
 TCPClient:= TIdTCPClient.Create;
 TCPClient.CreateIOHandler(TIdEnhancedioHandler);
 TCPClient.ConnectTimeout:= 1000;
 TCPClient.ReadTimeout:= -1;
 TCPClient.Host:= AHost;
 TCPClient.Port:= APort;
 RetSuccess:= False;
 RetMessage:= 'UnkNown error.';
end;

procedure TMainClient.Execute;
var CMD: Cardinal;
begin
 TCPClient.Connect;
 TCPClient.socket.Write(CMD);
end;

解决方法

从Indy帮助中我了解到...

帮助太旧了,信息已经过时了。

我必须使用CreateIOHandler并指定我的自定义IOHandler类。

您可以这样做,但实际上并不需要。您可以在调用TIdTCPClient.IOHandler之前直接将自定义类的实例直接分配给TIdTCPClient.Connect()属性,例如:

TCPClient := TIdTCPClient.Create;
TCPClient.IOHandler :- TIdEnhancedIOHandler.Create(TCPClient);
...

我这样做了,但出现一个异常,提示未安装此类。

这意味着Indy内部的GIOHandlerClassList不包含任何从您指定给CreateIOHandler()的类类型派生的类类型。

如何安装?保存列表的变量GIOHandlerClassList是私有的...

您需要在运行时以自定义类类型调用公共RegisterIOHandler()SetDefaultClass()类方法,例如在您单位的initialization部分,例如:

initialization
  TIdEnhancedIOHandler.RegisterIOHandler();

但是,Indy中唯一实际使用CreateIOHandler()的东西是TIdSimpleServer,因此在这种情况下无需“注册”您的自定义类。

另一方面,如果未分配TIdTCPClient.Connect()TIdIOHandler.MakeDefaultIOHandler()会调用IOHandler,并使用GIOHandlerClassDefault(由TIdIOHandler.SetDefaultClass()设置(也称为RegisterIOHandler())。因此,如果您希望TIdTCPClient为您创建自定义类类型的对象,则至少需要调用SetDefaultClass(),例如:

initialization
  TIdEnhancedIOHandler.SetDefaultClass();

无论哪种方式,RegisterIOHandler() / SetDefaultClass()只能被调用一次,例如在程序启动时。


更新:您收到一个抽象错误,因为您是从TIdIOHandlerSocket(它是一个抽象类)派生您的类的,因为它没有实现在ReadDataFromSource()中声明为WriteDataToTarget()的{​​{1}}和abstract方法。您需要改为从TIdIOHandler派生您的类,而该类又从TIdIOHandlerStack派生并实现这些方法。