そのような低レベルのコミュニケーションでは、どのようなコミュニケーションにおいても完全なメッセージを受け取ることに頼ることはできません。また、一度に 1 つのメッセージしか受信できないことに依存することもできません。
完全なメッセージでのみ通知することを保証する何かを実装する必要があります。
そのためには、完全なメッセージ (ヘッダーと終了フラグ) を受信するまで受信データを保存する必要があります。
TMessageBuffer
これは、着信データと完全なメッセージを処理するクラスを持つ小さなコンソール アプリです。
program so_22436319;
{$APPTYPE CONSOLE}
{$R *.res}
uses
SysUtils;
type
TMessageBuffer = class
private
FBuffer : string;
FMsgPart : Boolean;
procedure DoHandleMessage( const CompleteMessage : string );
public
procedure AddData( const Data : string );
end;
procedure Test;
var
LMsgBuffer : TMessageBuffer;
begin
LMsgBuffer := TMessageBuffer.Create;
try
// receive complete message
LMsgBuffer.AddData( '!A243B324C213D300#' );
// receive 2 complete message in one go
LMsgBuffer.AddData( '!A243B324C213D300#!A243B324C213D300#' );
// receive parts of the message
LMsgBuffer.AddData( '!A243B324' );
LMsgBuffer.AddData( 'C213D300#!A243' );
LMsgBuffer.AddData( 'B324C213D300#!A' );
LMsgBuffer.AddData( '243B324C2' );
LMsgBuffer.AddData( '13D300#' );
finally
LMsgBuffer.Free;
end;
end;
{ TMessageBuffer }
procedure TMessageBuffer.AddData( const Data : string );
var
LIdx : Integer;
LChar : Char;
begin
for LIdx := 1 to Length( Data ) do
begin
LChar := Data[LIdx];
if FMsgPart then
if LChar = '#' then
begin
DoHandleMessage( FBuffer );
FMsgPart := False;
FBuffer := '';
end
else
begin
FBuffer := FBuffer + LChar
end
else if LChar = '!' then
begin
FMsgPart := True;
end;
end;
end;
procedure TMessageBuffer.DoHandleMessage( const CompleteMessage : string );
begin
Writeln( 'MSG: ', CompleteMessage );
end;
begin
try
Test;
except
on E : Exception do
Writeln( E.ClassName, ': ', E.Message );
end;
ReadLn;
end.
生成された出力は
MSG: A243B324C213D300
MSG: A243B324C213D300
MSG: A243B324C213D300
MSG: A243B324C213D300
MSG: A243B324C213D300
MSG: A243B324C213D300
このクラスは、ヘッダーと終了文字を削除します。これは、トランスポート プロトコルの一部であり、不要になったためです。ただし、必要に応じて追加できます。