Я создал два объекта 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;





Проблема в том, что единственное место, где вы на самом деле читаете входящие данные в две InputBuffer, находится в событии таймера. Без двух вызовов Connected() (которые выполняют внутреннее чтение) InputBuffers всегда будут пустыми, поэтому потоку нечего делать.
Избавьтесь от таймера и используйте вместо него 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;