Этот код, который вы отправили как ответ, неверен.
Во-первых, вы не можете использовать BytesToString()
для произвольных байтовых блоков, которые не будут корректно обрабатывать многобайтовые кодировки, такие как UTF-8. .
Кроме того, вы неправильно ищете терминатор EOT. Нет гарантии, что это будет последний байт RxBuf
после каждого чтения, если клиент отправляет несколько сообщений XML. И даже если бы это было так, использование Copy(BytesToString(), ...)
для извлечения его в string
никогда не приведет к пустой строке, как ожидает ваш код.
Если клиент отправляет терминатор EOT в концеXML, нет необходимости в ручном цикле чтения. Просто вызовите TIdIOHandler.ReadLn()
с помощью терминатора EOT и позвольте ему обрабатывать циклы чтения внутри, пока не будет достигнут EOT.
Кроме того, вызовы CoInitialize()
и CoUninitialize()
должны выполняться в OnConnect
иСобытия OnDisconnect
соответственно (на самом деле их лучше вызывать в потомке TIdThreadWithTask
, назначенном свойству TIdSchedulerOfThread.ThreadClass
, но это уже более сложная тема в другой раз).
Попробуйте что-то похожееэто:
procedure TFrmMain.IdTCPServer1Connect(AContext: TIdContext);
begin
CoInitialize(nil);
AContext.Connection.IOHandler.DefStringEncoding := IndyTextEncoding_UTF8;
end;
procedure TFrmMain.IdTCPServer1Disconnect(AContext: TIdContext);
begin
CoUninitialize();
end;
procedure TFrmMain.IdTCPServer1Execute(AContext: TIdContext);
var
XML: string;
begin
cdsSurescripts.Close;
XML := AContext.Connection.IOHandler.ReadLn(#4);
Display('CLIENT', XML);
AContext.Connection.IOHandler.WriteLn('000');
end;
Лично я бы выбрал другой подход. Я бы предложил использовать синтаксический анализатор XML, который поддерживает push-модель. Затем вы можете прочитать произвольные блоки байтов из соединения и вставить их в анализатор, позволяя ему запускать события для завершенных элементов XML, пока не будет достигнут терминатор. Таким образом, вам не нужно тратить время и память на буферизацию всего XML в памяти, прежде чем вы сможете затем обработать его.