Delphi 2009, Indy 10, TIdTCPServer.OnExecute, как получить все байты в InputBuffer - PullRequest
6 голосов
/ 13 февраля 2009

Я возиться с Indy 10, поставляемой с Delphi 2009, и у меня возникают проблемы с получением всех данных от IOHandler при запуске OnExecute ...

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.Connection.IOHandler.InputBuffer.Size не кажется надежным и часто возвращает 0, но при следующем запуске через OnExecute он выберет нужное количество байтов, но это слишком поздно.

По сути, я хочу иметь возможность просто захватить все данные, вставить их в UTF8String ( не строка Unicode), а затем проанализировать специальный маркер. Поэтому у меня нет заголовков и сообщений переменной длины. Кажется, что Indy 10 IOHandlers не настроен для этого, или я просто неправильно его использую.

Было бы неплохо сделать что-то вроде передачи буфера определенного размера, заполнить его как можно больше и вернуть количество фактически заполненных байтов, а затем продолжить работу, если их больше.

В качестве статуса TIdSchedulerOfFiber, это выглядит очень интересно, работает ли оно? Кто-нибудь использует это? Я заметил, что он не входит в стандартную версию Delphi 2009.

Обновление: Я нашел сообщение: = AContext.Connection.IOHandler.ReadLn (# 0, enUTF8); который работает, но я все еще хотел бы знать ответ на поставленный выше вопрос, потому что он основан на блокировке ввода-вывода? Что еще больше увлекает этот TIdSchedulerOfFiber.

Ответы [ 2 ]

16 голосов
/ 13 февраля 2009

Вы не должны использовать Readable () таким образом. Вместо этого попробуйте следующее:

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;

В качестве альтернативы:

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;

Что касается TIdSchedulerOfFiber - пакет SuperCore фактически мертв в настоящее время. Он не разрабатывался в течение очень длительного времени и не соответствует новейшей архитектуре Indy 10. Мы можем попытаться воскресить его позже, но это не входит в наши планы на ближайшее будущее.

1 голос
/ 11 мая 2011
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; 
...