2

メソッドパラメータとしてバイナリデータのストリームをサーバーに渡す必要があるTCP/IPプロトコルを使用してDelphiXE2でDataSnapプロジェクトに取り組んでいます。私が遭遇している問題は、ストリームの内容に約32KBのサイズ制限があるように見えることです。この制限を超えると、サーバーで受信されたストリームは空になります。追加のメソッドパラメータを渡すと、そのまま到着するため、パラメータレベルで問題が発生しているようです。

DataSnapサービスクラスの宣言方法は次のとおりです。

  TDataSnapTestClient = class(TDSAdminClient)
  private
    FSendDataCommand: TDBXCommand;
  public
    constructor Create(ADBXConnection: TDBXConnection); overload;
    constructor Create(ADBXConnection: TDBXConnection; AInstanceOwner: Boolean); overload;
    destructor Destroy; override;
    procedure SendData(Data: TStream);
  end;

少なくともジム・ティアニーの記事によれば、私が使用しているアプローチはうまくいくはずです。とは言うものの、Delphi 2009以降、JimTierneyのサンプルコードを壊した変更があったようです。

DataSnapサーバーメソッドのストリームパラメータ

この問題を解決する方法についてのアイデアをいただければ幸いです。

4

2 に答える 2

9

DataSnap はデータを 32k チャンクで転送します。受信側は、すべてのチャンクが再構築されるまで、受信されるバイト数を知る方法がありません。すべてのデータが受信されると、DataSnap はTStreamデータを受信した のサイズを設定しないため、ストリーム内のバイト数を認識している別のストリームにデータを移動するまで、データを使用できません。

DataSnap サーバーから 32k+ をプルすることは、DataSnap サーバーに 32k+ をプッシュすることと同じではないことはわかっていますが、これもうまくいくかもしれません。TStreamDataSnap サーバーがデータの受信を終了した後、次のコードを実行してみてください。

procedure CopyStreamToMemoryStream(const ASource: TStream; var ADest: TMemoryStream; const Rewind: Boolean = True);
const
  LBufSize = $F000;
var
  LBuffer: PByte;
  LReadCount: Integer;
begin
  GetMem(LBuffer, LBufSize);
  ADest.Clear;
  try
    repeat
      LReadCount := ASource.Read(LBuffer^, LBufSize);
      if LReadCount > 0 then
        ADest.WriteBuffer(LBuffer^, LReadCount);
    until LReadCount < LBufSize;
  finally
    FreeMem(LBuffer, LBufSize);
  end;
  if Rewind then
    ADest.Seek(0, TSeekOrigin.soBeginning);
end;

このコードを見つけた場所 (何年も前) を思い出せないので、クレジットが必要な場所でクレジットを与えることはできませんが、何年もの間、確実に機能しています。

于 2012-08-23T19:55:39.683 に答える
0

考えてみたところ、特にファイルが非常に大きい場合、データを別のメモリ ストリームに転送するとメモリが無駄になることに気付きました。あとは、バイト数を数えてストリーム サイズを設定するだけですよね?!

procedure FixStream(const AStream: TStream);
const
  LBufSize = $F000;
var
  LBuffer: PByte;
  LReadCount, StreamSize: Integer;
begin
  GetMem(LBuffer, LBufSize);
  try
    StreamSize := 0;
    repeat
      LReadCount := AStream.Read(LBuffer^, LBufSize);
      Inc(StreamSize, LReadCount);
    until LReadCount < LBufSize;
    AStream.Size := StreamSize;
  finally
    FreeMem(LBuffer, LBufSize);
  end;
end;

試してみませんか?私は今コードをテストすることができません。

于 2012-08-24T01:38:18.597 に答える