web-dev-qa-db-ja.com

WCF経由で画像を送信する効率的な方法は?

私は、VNCのようなカスタムリモートコントロールアプリケーションを最初から作成することで、WCF、LINQ、およびその他のいくつかのテクノロジを学習しています。私は3つの主要な目標を念頭に置いてそれを作成しています:

  1. サーバーは、完全なデスクトップアクセスではなく、アプリケーションレベル(つまり、シームレスウィンドウ)で「リモートコントロール」を提供します。
  2. クライアントは、サーバー上で実行されているアプリケーションをいくつでも選択して、それぞれの画像のストリームを受信できます。
  3. クライアントは、複数のサーバーに同時に接続できます。

現在、WCFを使用して、送信されるウィンドウを表すバイトの配列を送信しています。

using (var ms = new MemoryStream()) {
    window.GetBitmap().Save(ms, ImageFormat.Jpeg);
    frame.Snapshot = ms.ToArray();
}

GetBitmapの実装:

var wRectangle = GetRectangle();
var image = new Bitmap(wRectangle.Width, wRectangle.Height);
var gfx = Graphics.FromImage(image);

gfx.CopyFromScreen(wRectangle.Left, wRectangle.Top, 0, 0, wRectangle.Size, CopyPixelOperation.SourceCopy);

return image;

次に、WCF(TCPBindingであり、常にLAN経由)を介してクライアントに送信され、次のような境界線のない空白のWindowsフォームに再構築されます。

using (var ms = new MemoryStream(_currentFrame.Snapshot))
{
    BackgroundImage = Image.FromStream(ms);
}

このプロセスをCPUとメモリの両方の使用量で可能な限り効率的にし、帯域幅を3位にしたいと思います。サーバーごとに10以上のアプリケーションを使用して、クライアントを5つ以上のサーバーに接続することを目指しています。

私の既存の方法は(これらのテクノロジーを使い続けながら)最善のアプローチですか?それを改善するために私にできることはありますか?

私が調べているアイデア(しかし私は経験がありません):

  • .Netソリューションの代わりに、オープンソースのグラフィックライブラリを使用して画像をキャプチャおよび保存します。
  • JPGではなくPNGまたは別の画像タイプとして保存します。
  • 毎回、完全な画像ではなく画像のデルタを送信します。
  • ウィンドウを「記録」して、画像スナップショット(mpeg?)の代わりに圧縮ビデオストリームを作成してみてください。
24

この点に注意する必要があります。

afterこのすべてのステップを通過し、最終的なコードに満足したら、 VncSharpソースコード をダウンロードできます。 RFBプロトコル(ウィキペディアエントリ)"a simple protocol for remote access to graphical user interfaces. Because it works at the framebuffer level it is applicable to all windowing systems and applications, including X11, Windows and Macintosh. RFB is the protocol used in VNC (Virtual Network Computing)."を実装します

21
Rubens Farias

私はしばらく前に同様のプロジェクトに取り組みました。これが私の一般的なアプローチでした:

  • キャプチャしたビットマップを32x32のタイルにラスタライズしました
  • フレーム間でどのタイルが変更されたかを判断するために、安全でないコードを使用して、一度に64ビットずつ比較しました。
  • デルタタイルのセットで、圧縮率を向上させるためにPNGフィルターの1つを適用し、 Paethフィルター で最良の結果が得られました。
  • 使用 DeflateStream フィルタリングされたデルタを圧縮する
  • 使用 BinaryMessageEncoding デフォルトのBase64エンコードバージョンの代わりにバイナリでデータを送信するためのサービスへのカスタムバインディング

クライアント側の考慮事項。 WCFサービスを介して転送される大量のデータを処理するときに、 HttpTransportBinding および XmlDictionaryRenderQuotas の一部のパラメーターがかなり控えめな値に設定されていることがわかりました。だからあなたはそれらを増やしたいと思うでしょう。

4
Yannick Motton

これをチェックしてください: 大規模なデータとストリーミング (WCF)

4
DxCK

クライアント/サーバー間でデータを送信する最速の方法は、1つまたは複数のバイト配列を送信することです。そうすれば、WCFはデータに対してカスタムシリアル化を行う必要がありません。

そうは言った。 System.Drawingの画像ではなく、新しいWPF/.Net3.5ライブラリを使用して画像を圧縮する必要があります。 System.Windows.Media.Imaging名前空間の関数は、古い関数よりも高速であり、引き続きwinformsで使用できます。

圧縮が進むべき道であるかどうかを知るためには、シナリオをベンチマークして、圧縮/解凍時間が圧縮されていないすべてのバイトを転送するのとどのように比較されるかを知る必要があります。

インターネット経由でデータを転送する場合は、圧縮が確実に役立ちます。同じマシンまたはLAN上のコンポーネント間では、利点はそれほど明白ではない場合があります。

また、画像を圧縮してから、データをチャンクして、クライアントで一緒にパズルを解くチャンクIDを使用して非同期に送信することもできます。 Tcp接続は開始が遅く、時間の経過とともに帯域幅が増加するため、2つまたは4つを同時に開始すると、合計転送時間が短縮されます(すべて送信するデータの量によって異なります)。圧縮された画像のバイトをチャンク化することも、実際の画像でタイルを作成するよりも論理的に簡単です。

要約:System.Windows.Media.Imagingは、現在のコードと比較して、CPUと帯域幅の両方の面で役立つはずです。記憶に関しては、私は同じことを推測します。

1
Mikael Svenson

画像全体をキャプチャする代わりに、画像の小さなサブセクションを送信するだけです。意味:左上隅から始めて、10x10ピクセルの画像を送信し、次に10ピクセルを「移動」して、次の10pxの正方形を送信します。次に、数十の小さな画像を送信してから、クライアントでペイントされた完全な画像を更新できます。 RDCを使用してリモートマシンで画像を表示したことがある場合は、おそらくこの種のスクリーンペイントを実行しているのを見たことがあるでしょう。

小さい画像セクションを使用すると、デルタも分割できるため、現在のセクションで何も変更されていない場合は、安全にスキップして、スキップすることをクライアントに通知してから、次のセクションに進むことができます。

あなたは間違いなく画像を送信するために圧縮を使用したいと思うでしょう。ただし、gZipと同様の圧縮を使用するとファイルサイズが小さくなるかどうか、またはイメージコーデックを使用するとより良い結果が得られるかどうかを確認する必要があります。私は比較を行ったことがないので、特定の方法で言うことはできません。

0
Jacob Ewald
Bitmap scrImg = new Bitmap(Screen.PrimaryScreen.Bounds.Width, Screen.PrimaryScreen.Bounds.Height);
Graphics scr;
scr.CopyFromScreen(new Point(0, 0), new Point(0, 0), Screen.PrimaryScreen.Bounds.Size);
testPictureBox.Image = (Image)scrImg;

このコードを使用して画面をキャプチャします。

0
OmarElsherif
  1. あなたの解決策は私には問題ないように見えますが、(他の人がしたように)タイルを使用し、可能な場合はトラフィックを圧縮することをお勧めします。さらに、クライアントのデルタに共通の「ベース」があることを確認するために、イメージ全体を時々送信する必要があると思います。

  2. おそらく、ビデオストリーミング用のRTP-H263など、ストリーミング用の既存のソリューションを使用できます。それはうまく機能し、圧縮を使用し、十分に文書化され、広く使用されています。次に、WCF部分をスキップして、ストリーミング部分に直接移動できます(TCPまたはUDP経由)。ソリューションを本番環境に移行する必要がある場合は、H263ストリーミングアプローチの方が適している可能性があります。応答性とネットワーク使用量の。

0
Ron Klein