2

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;

データ交換順序は次のとおりです。

  1. クライアントがサーバーにリクエストを送信し、

  2. サーバーはリクエストを読み取り、クライアントに応答を返します。

  3. クライアントは答えを読み上げます。

手順 3 で間違ったデータが表示されます。

多分私は何か一般的に間違ったことをしていますか?

サーバーにリクエストを送信して受信バッファーをクリアする直前に ReadBytes() を試みましたが、他の多くのことを試したので、それも役に立ちません...

今、私はアイデアがありません:(

4

1 に答える 1