如何从具有IdTCPClient的服务器等待字符串?

Sad*_*deh 2 sockets delphi indy tcpclient

我有一个IdTelnet(indy 10.1)的问题.我无法以Unicode模式从服务器读取数据.现在我想用IdTCPClient编写telnet终端.

服务器有时会发送一行,有时会发送越来越多的行.但发送之间没有固定的时间.

现在我的问题是,当我必须从InBuffer读取数据时.

或者当我必须使用ReadLn函数从服务器读取数据时,我必须运行ReadLn多少次?

Rem*_*eau 7

TIdTelnet是一个多线程组件.它有一个内部线程,可以从套接字连续读取,TIdTelnet.OnDataAvailable每当有数据缓冲区可用时触发事件.

TIdTelnetTIdTCPClient后代.查看IdTelnet.pas源文件以了解它是如何实现的.您可以在自己的代码中执行类似的操作,TIdIOHandler.ReadLn()在您自己的线程中调用,例如:

type
  TMyThread = class(TThread)
  private
    FConn: TIdTCPConnection;
  protected
    procedure Execute; override;
  public
    constructor Create(AConn: TIdTCPConnection); reintroduce;
  end;

constructor TMyThread.Create(AConn: TIdTCPConnection);
begin
  inherited Create(False);
  FConn := AConn;
end;

procedure TMyThread.Execute;
var
  S: String;
begin
  while not Terminated do
  begin
    S := FConn.IOHandler.ReadLn(...);
    ...
  end;
end;

var
  Thread: TMyThread = nil;

procedure TForm1.ConnectButtonClick(Sender: TObject);
begin
  IdTCPClient1.Connect;
  try
    Thread := TMyThread.Create(IdTCPClient1);
  except
    IdTCPClient1.Disconnect;
    raise;
  end;
end;

procedure TForm1.DisconnectButtonClick(Sender: TObject);
begin
  if Assigned(Thread) then Thread.Terminate;
  try
    IdTCPClient1.Disconnect;
  finally
    if Assigned(Thread) then
    begin
      Thread.WaitFor;
      FreeAndNil(Thread);
    end;
  end;
end;
Run Code Online (Sandbox Code Playgroud)

如果您不想使用线程,则可以使用计时器.为了确保您的计时器线程(例如主线程)没有被不必要地阻塞,TIdIOHandler.CheckForDataOnSource()只要TIdIOHandler.InputBuffer空的时候使用带有小超时的方法,然后TIdIOHandler.ReadLn()在数据可用时调用,例如:

procedure TForm1.ConnectButtonClick(Sender: TObject);
begin
  IdTCPClient1.Connect;
  ReadTimer.Enabled := True;
end;

procedure TForm1.DisconnectButtonClick(Sender: TObject);
begin
  ReadTimer.Enabled := False;
  IdTCPClient1.Disconnect;
end;

procedure TForm1.ReadTimerElapsed(Sender: TObject);
var
  S: String;
begin
  if IdTCPClient1.IOHandler.InputBufferIsEmpty then
  begin
    IdTCPClient1.IOHandler.CheckForDataOnSource(10);
    if IdTCPClient1.IOHandler.InputBufferIsEmpty then Exit;
  end;
  S := IdTCPClient1.IOHandler.ReadLn(...);
  ...
end;
Run Code Online (Sandbox Code Playgroud)