Indy имеет функцию BytesToString()
в единице IdGlobal
, поэтому вам не нужно конвертировать TIdBytes
в string
вручную:
RStr := BytesToString(data);
A string
обычно индексируется 1 (если вы не компилируете для мобильных устройств и не используете {$ZEROBASEDSTRINGS OFF}
), поэтому copy(RStr,1091,8)
следует использовать 1092 вместо 1091, так как вы читаете 1099 байт вместо 1098 байт:
copy(RStr,1092,8)
Но Indy имеет функции TextStartsWith()
и TextEndsWith()
, также в модуле IdGlobal
, поэтому вам не нужно извлекать и сравнивать подстроки вручную:
if TextStartsWith(RStr, '00D0') and TextEndsWith(RStr, '00000000') then
Теперь, как говорится, если ваши данные сокетов действительно текстовые по природе, а не двоичные, вы должны использовать метод TIdIOHandler.ReadString()
вместо метода TIdIOHandler.ReadBytes()
:
RStr := AContext.Connection.IOHandler.ReadString(1099);
В качестве альтернативы, TIdIOHandler
также имеет WaitFor()
и ReadLn()
методы для чтения текста с разделителями, например:
AContext.Connection.IOHandler.WaitFor('00D0');
RStr := '00D0' + AContext.Connection.IOHandler.ReadLn('00000000') + '00000000';
или
AContext.Connection.IOHandler.WaitFor('00D0');
RStr := '00D0' + AContext.Connection.IOHandler.WaitFor('00000000', True, True);
Наконец, TIdTCPServer
является многопоточным компонентом, его событие OnExecute
запускается в контексте рабочего потока, а не основного потока пользовательского интерфейса. Таким образом, вы ДОЛЖНЫ синхронизироваться с основным потоком пользовательского интерфейса при доступе к пользовательскому интерфейсу, например, с помощью методов класса RTL TThread.Queue()
или TThread.Synchronize()
, классов Indy TIdNotify
или TIdSync
и т. Д. Плохие вещи могут и обычно do случаются при доступе к элементам управления UI снаружи основного потока UI.
ОБНОВЛЕНИЕ : в комментариях вы говорите, что данные на самом деле в байтах, а не в текстовых символах. И что вам нужно сбросить байты, прежде чем вы начнете читать записи. В этом случае вам не следует конвертировать байты в string
. Вместо этого обрабатывайте байты как есть, например:
procedure TForm2.IdTCPServer1Execute(AContext: TIdContext);
var
data: TIdBytes;
b: Byte;
begin
b := AContext.Connection.IOHandler.ReadByte;
repeat
if b <> $00 then Exit;
b := AContext.Connection.IOHandler.ReadByte;
until b = $D0;
SetLength(data, 2);
data[0] = $00;
data[1] = $D0;
AContext.Connection.IOHandler.ReadBytes(data, 1097, True);
repeat
if {(PWord(@data[0])^ = $D000)}(data[0] = $00) and (data[1] = $D0)
and (PUInt32(@data[1091])^ = $00000000) then
begin
TThread.Queue(nil,
procedure
begin
Memo14.Lines.Add( 'Frame added to database.' );
end;
);
end else
begin
TThread.Queue(nil,
procedure
begin
Memo14.Lines.Add( 'error invalid Frame ...' );
end;
);
end;
AContext.Connection.IOHandler.ReadBytes(data, 1099, False);
until False;
end;