Delphi で TIdTCPClient/TIdTcpServer インディ コンポーネントを使用してクライアント サーバー アプリケーションを作成しています。
通常、データ転送は正常に機能しますが、サーバーから間違ったデータを読み取ることがよくあります。現在のリクエストではなく、以前のリクエストの回答を取得します。
デバッグ中、両方のアプリがローカルで動作しているため、転送中にデータが失われることはありません。
タイムアウトは 1000 ~ 3000 ミリ秒です。これは、最初の応答を受信する前に 2 番目の要求を送信することを回避するのに十分です。
単純なデータ形式を使用します。最初の 4 バイトはデータ パケット長で、残りはその長さのバイナリ データです。
サーバー側のコードは次のとおりです (文字列のみを送信するために単純化されています。バイナリ バッファーも同じように使用しますが、このコードの方が理解と確認が簡単です)。
Var
lng: LongInt;
ib: TIdBytes;
begin
// Prepare data to send:
lng:=length(s);// s is an AnsiString to be sent
SetLength(ib,lng+4);
Move(lng,ib[0],4);
Move(s[1],ib[4],length(s));
// Send:
AContext.Connection.IOHandler.WriteDirect(ib);
end;
リクエストを送信するためのクライアント側のコードは同じです (最後の行で TIdTcpClient.IOHandler.WriteDirect() を呼び出します)。サーバーの回答を読み取るためのクライアント側のコードは次のとおりです。
Var
ib: TIdBytes;
size,done,lng: LongInt;
begin
Result:=false;
// answer length:
try
SetLength(ib,0);
tcp.IOHandler.ReadBytes(ib,4,false);
Move(ib[0],size,4);
if length(ib)<0 then Exit;// wrong data
except
on E: Exception do;// code skipped
end;
// read answer body:
done:=0;
b.Clear;// b is my buffer, TStream descendant
while done<size do
begin
lng:=Min(size-done,MaxBlockSize);
// read:
SetLength(ib,0);// to be sure
tcp.IOHandler.ReadBytes(ib,lng,false);
if length(ib)=0 then Exit;// error reading
// append my buffer:
b.Wr(ib[0],length(ib));
// progress:
Inc(done,length(ib));
end;
end;
データ交換順序は次のとおりです。
クライアントがサーバーにリクエストを送信し、
サーバーはリクエストを読み取り、クライアントに応答を返します。
クライアントは答えを読み上げます。
手順 3 で間違ったデータが表示されます。
多分私は何か一般的に間違ったことをしていますか?
サーバーにリクエストを送信して受信バッファーをクリアする直前に ReadBytes() を試みましたが、他の多くのことを試したので、それも役に立ちません...
今、私はアイデアがありません:(