Indy TCP-循环读取数据 [英] Indy TCP - Read data in a loop

查看:163
本文介绍了Indy TCP-循环读取数据的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

TCP服务器每8毫秒连续发送一次数据帧.我想对一个能够接收这些数据帧的客户端进行编程. Indy 9中是否有任何程序可以知道缓冲区中是否有可用数据?

A TCP server is sending data frames continuosly every 8ms. I want to program a client able to receive these data frames. Is there any procedure in Indy 9 to know if there is data available in the buffer?

我当前的程序如下(我正在使用线程):

My current programs is the following (I am using a Thread):

procedure TThreadRead.Execute;
var
  buffer: array [0..755] of byte;
  //s1: string;
  //i: integer;
begin
  IdTCPClient1.RecvBufferSize:= 756;
  IdTCPClient1.Connect;
  while Terminated = false do
  begin
    if IdTCPClient1.InputBuffer.Size = 0 then
       IdTCPClient1.ReadFromStack(True,0,False);
    while IdTCPClient1.InputBuffer.Size > 0 do
    begin
       ReadBuffer(buffer, FClient.InputBuffer.Size);
       //s1:= '';
       //For i:=0 To Length(buffer)-1 Do
       //  s1:=s1+IntToHex(Ord(buffer[i]),2); //Read values-->global var
       //Form1.Memo1.Text:=s1;
    end;
  end;
end;

是否有更有效的解决方案来连续读取TCP数据(例如UDP中的onread事件)?

Is there any more efficient solution for reading TCP data continuously (like onread event in UDP)?

谢谢.

推荐答案

TIdTCPClient不是异步组件.它不会告诉您数据何时到达.您需要使用计时器或线程来定期轮询套接字以获取新数据(TIdUDPServer使用内部线程来触发其OnUDPRead事件),例如:

TIdTCPClient is not an asynchronous component. It does not tell you when data arrives. You need to use a Timer or a Thread to periodically poll the socket for new data (TIdUDPServer uses an internal thread to trigger its OnUDPRead event), eg:

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

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

procedure TForm1.Timer1Timer(Sender: TObject);
var
  s1: string;
begin
  s1 := IdTCPClient1.CurrentReadBuffer;
  ...
end;

话虽如此,CurrentReadBuffer()通常不是最佳选择.通常,您会执行以下操作:

With that said, CurrentReadBuffer() is generally not the best choice to use. Typically you would do something more like this instead:

procedure TForm1.Timer1Timer(Sender: TObject);
begin
  Timer1.Enabled := False;

  IdTCPClient1.ReadFromStack(True, 0, False);

  while IdTCPClient1.InputBuffer.Size > 0 do
  begin
    // read one complete frame and process as needed ...
  end;

  Timer1.Enabled := True;
end;

更新:给定有关帧结构和切换到线程的新信息,您应该这样做:

Update: given new information about the frame structure and your switch to a thread, you should be doing this instead:

procedure TThreadRead.Execute;
var
  buffer: array of Byte;
  numbytes: Integer;
begin
  SetLength(buffer, 0);
  IdTCPClient1.Connect;
  try
    while not Terminated do
    begin
      numbytes := StrToInt('$' + IdTCPClient1.ReadString(8)) - 8;
      if numbytes <> Length(buffer) then
        SetLength(buffer, numbytes);
      if numbytes > 0 then
        IdTCPClient1.ReadBuffer(buffer[0], numbytes);
      // process buffer up to numbytes as needed...
    end;
  finally
    IdTCPClient1.Disconnect;
  end;
end;

这篇关于Indy TCP-循环读取数据的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆