FMX、 Delphi 、TIdTCPClient

wnvonmuf  于 2023-04-29  发布在  其他
关注(0)|答案(1)|浏览(191)

我创建了两个TIdTCPClient对象,并将它们连接到同一台服务器。
服务器从一个客户端接收字节并将其发送到另一个客户端。这个客户端将其发送到第一个客户端,依此类推。
问题是,它不工作后,我按下按钮,而定时器被禁用。但如果我启动定时器,它就会和定时器的频率一起工作。

type
  TForm2 = class(TForm)
    Client1: TIdTCPClient;
    Client2: TIdTCPClient;
    Timer1: TTimer;
    Button1: TButton;
    procedure FormCreate(Sender: TObject);
    procedure Timer1Timer(Sender: TObject);
  private
    idThreadComponent : TIdThreadComponent;
    procedure IdThreadComponentRun(Sender: TIdThreadComponent);
    procedure IdTCPClientConnected(Sender: TObject);
  end;

procedure TForm2.FormCreate(Sender: TObject);
  begin
    idThreadComponent:= TIdThreadComponent.Create();
    idThreadComponent.OnRun := IdThreadComponentRun;

    Client1.Port:= 1202;
    Client1.Host:= 'localhost';
    Client2.Port:= 1203;
    Client2.Host:= 'localhost';

    Client1.OnConnected:= IdTCPClientConnected;
    Client2.OnConnected:= IdTCPClientConnected;

    Client1.Connect;
    Client2.Connect;
  end;

procedure TForm2.IdThreadComponentRun(Sender: TIdThreadComponent);
  var
    Rx: TIDBytes;
  begin
    if not Client1.IOHandler.InputBufferIsEmpty then
      begin
        Client1.IOHandler.ReadBytes(Rx, Client1.IOHandler.InputBuffer.Size);
        if Length(Rx) > 0 then
          begin
            Client2.IOHandler.Write(Rx);
          end
      end;

    if not Client2.IOHandler.InputBufferIsEmpty then
      begin
        Client2.IOHandler.ReadBytes(Rx, Client2.IOHandler.InputBuffer.Size);
        if Length(Rx) > 0 then
          begin
            Client1.IOHandler.Write(Rx);
          end;
      end;
  end;

procedure TForm2.IdTCPClientConnected(Sender: TObject);
  begin
    IdThreadComponent.Active  := True;
  end;

procedure TForm2.Button1Click(Sender: TObject);
  var
    Tx: TIDBytes;
  begin
    SetLength(Tx, 1);
    Client1.IOHandler.Write(Tx,length(Tx));
  end;

procedure TForm2.Timer1Timer(Sender: TObject);
  begin
    if not Client1.Connected then
      begin
      end;
    if not Client2.Connected then
      begin
      end;
  end;
5t7ly7z5

5t7ly7z51#

问题是,您实际阅读传入数据到两个InputBuffer的唯一位置是计时器事件。如果没有对Connected()的两个调用(在内部执行读取),InputBuffer s将始终为空,因此线程没有工作要做。
去掉计时器,让线程使用CheckForDataOnSource(),例如:

procedure TForm2.IdThreadComponentRun(Sender: TIdThreadComponent);
  var
    Rx: TIdBytes;
  begin
    Client1.IOHandler.CheckForDataOnDource(0);
    Client1.IOHandler.CheckForDisconnect;
    if not Client1.IOHandler.InputBufferIsEmpty then
      begin
        Client1.IOHandler.ReadBytes(Rx, -1);
        Client2.IOHandler.Write(Rx);
        Rx := nil;
      end;

    Client2.IOHandler.CheckForDataOnSource(0);
    Client2.IOHandler.CheckForDisconnect;
    if not Client2.IOHandler.InputBufferIsEmpty then
      begin
        Client2.IOHandler.ReadBytes(Rx, -1);
        Client1.IOHandler.Write(Rx);
        Rx := nil;
      end;
  end;

或者,只使用2个单独的阅读线程,并让ReadBytes()正常阻塞,例如:

procedure TForm2.IdThreadComponent1Run(Sender: TIdThreadComponent);
  var
    Rx: TIdBytes;
  begin   
    Client1.IOHandler.ReadBytes(Rx, -1);
    Client2.IOHandler.Write(Rx);
  end;

procedure TForm2.IdThreadComponent2Run(Sender: TIdThreadComponent);
  var
    Rx: TIdBytes;
  begin   
    Client2.IOHandler.ReadBytes(Rx, -1);
    Client1.IOHandler.Write(Rx);
  end;

相关问题