Delphi 2009, Indy 10, TIdTCPServer.OnExecute, jak pobrać wszystkie bajty w buforze wejściowym

Pogrywam sobie z Indy 10 dostarczonym z Delphi 2009 i mam problem z uzyskaniem wszystkich danych z Iohandlera, gdy onexecute odpala...

procedure TFormMain.IdTCPServerExecute(AContext: TIdContext);
var
  RxBufStr: UTF8String;
  RxBufSize: Integer;
begin

  if AContext.Connection.IOHandler.Readable then
  begin
    RxBufSize := AContext.Connection.IOHandler.InputBuffer.Size;
    if RxBufSize > 0 then
    begin
      SetLength(RxBufStr, RxBufSize);
      AContext.Connection.IOHandler.ReadBytes(TBytes(RxBufStr), RxBufSize, False);
    end;
  end;

end;

AContext.Połączenie.IOHandler.InputBuffer.Rozmiar nie wydaje się wiarygodny i często zwraca 0, ale przy następnym uruchomieniu przez OnExecute pobierze odpowiednią liczbę bajtów, ale to jest za późno.

Zasadniczo chcę być w stanie po prostu pobrać wszystkie dane, wrzucić je do UTF8String ( a nie Unicode string), a następnie parse dla specjalnego znacznika. Więc nie mam nagłówków i wiadomości mają zmienną długość. Wydaje się, że Indy 10 IOHandlers nie są do tego skonfigurowane lub po prostu używam go źle.

Byłoby miło zrobić coś takiego jak przekazanie bufora o określonym rozmiarze, wypełnienie go jak najwięcej i zwrócenie liczby rzeczywiście wypełnionych bajtów, a następnie kontynuowanie, jeśli jest ich więcej.

Na marginesie jaki jest status TIdSchedulerOfFiber, to wygląda bardzo ciekawie, czy to działa? Czy ktoś używasz go? Zauważyłem, że nie jest to jednak w standardowej instalacji Delphi 2009.

Update: znalazłem Msg: = AContext.Połączenie.IOHandler.ReadLn (#0, enUTF8); który działa, ale nadal chciałbym znać odpowiedź na powyższe pytanie, czy to dlatego, że opiera się na blokowaniu IO? Co sprawia, że jeszcze bardziej zależy na tym TIdSchedulerOfFiber.

Author: RRUZ, 2009-02-13

2 answers

Nie powinieneś używać Readable () w ten sposób. Spróbuj zamiast tego:

procedure TFormMain.IdTCPServerExecute(AContext: TIdContext);
var
  RxBuf: TIdBytes;
begin
  RxBuf := nil;
  with AContext.Connection.IOHandler do
  begin
    CheckForDataOnSource(10);
    if not InputBufferIsEmpty then
    begin
      InputBuffer.ExtractToBytes(RxBuf);
      // process RxBuf as needed...
    end;
  end;
end;

Alternatywnie:

procedure TFormMain.IdTCPServerExecute(AContext: TIdContext);
var
  RxBufStr: String; // not UTF8String
begin
  with AContext.Connection.IOHandler do
  begin
    CheckForDataOnSource(10);
    if not InputBufferIsEmpty then
    begin
      RxBufStr := InputBuffer.Extract(-1, enUtf8);

      // Alternatively to above, you can set the
      // InputBuffer.Encoding property to enUtf8
      // beforehand, and then call TIdBuffer.Extract()
      // without any parameters.
      //
      // Or, set the IOHandler.DefStringEncoding
      // property to enUtf8 beforehand, and then
      // call TIdIOHandler.InputBufferAsString()

      // process RxBufStr as needed...
    end;
  end;
end;

Co do TIdSchedulerOfFiber - Pakiet SuperCore jest faktycznie martwy w tym czasie. Nie pracował nad nim od bardzo dawna i nie jest na bieżąco z najnowszą architekturą Indy 10. Możemy próbować go wskrzesić w późniejszym terminie, ale nie jest to w naszych planach na najbliższą przyszłość.

 16
Author: Remy Lebeau,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2009-02-13 02:07:31
procedure TFormMain.IdTCPServerExecute(AContext: TIdContext); 
var
  RxBufStr: UTF8String;
  RxBufSize: Integer;
begin    
  if AContext.Connection.IOHandler.Readable then
  begin     
    AContext.Connection.IOHandler.ReadBytes(TBytes(RxBufStr),-1, False);
  end;
end; 
 1
Author: wushousheng,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2011-05-11 12:13:00