2012-06-04 1 views
2

TCP-сервер непрерывно передает кадры данных каждые 8 ​​мс. Я хочу запрограммировать клиента, способного принимать эти данные. Есть ли какая-либо процедура в Indy 9, чтобы узнать, имеются ли данные в буфере?Indy TCP - чтение данных в цикле

Моих текущих программ является следующее (я использую тему):

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 непрерывно (как onread событие в UDP)?

Заранее спасибо.

ответ

4

TIdTCPClient не является асинхронным компонентом. Он не сообщает вам, когда поступают данные. Вы должны использовать таймер или тему периодически опрашивать сокет для новых данных (TIdUDPServer использует внутреннюю резьбу, чтобы вызвать его OnUDPRead событие), например:

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(), как правило, не лучший выбор использовать. Как правило, вы могли бы сделать что-то больше, как это вместо:

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: дали новую информацию о структуре кадра и переключателю к потоку, вы должны делать это вместо:

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; 
+0

Я что-то не так, потому что ваш код не работает ... почему вы читаете из стека, когда inputbuffer.size = 0? Почему нет CurrentReadBuffer() лучший выбор для использования? Является ли TidTCPServer асинхронным компонентом? Может быть, проще использовать TCP-сервер для чтения данных ... – user1361263

+0

В моем случае IdTCPClient1.InputBuffer.Size всегда 0 ... – user1361263

+0

Indy не считывает данные из сокета (то есть Stack), пока вы не скажете ему прочитать что нибудь. Когда таймер запускается, он проверяет, является ли 'InputBuffer' пустым, и если это так, то вызывает' ReadFromStack() 'для чтения любых данных в настоящее время в сокете в тот момент, если они есть, и помещает их в' InputBuffer'. Код не пытается обрабатывать какие-либо кадры, пока данные не достигнут «InputBuffer» первым, что указывает на то, что есть что-то доступное для обработки. Если ваш 'InputBuffer' всегда пуст, даже после вызова' ReadFromStack() ', тогда сервер никогда не будет отправлять какие-либо данные вашему клиенту вообще. –

 Смежные вопросы

  • Нет связанных вопросов^_^