4

複数のサーバーへの複数の接続を使用して同時に (異なるスレッドで) ダウンロードするアプリを C# で作成しています。使用する帯域幅を制限できるようにしたいと考えています。

単一の接続の場合、ソリューションは簡単です。ここに投稿されたソリューションを使用します: http://www.codeproject.com/KB/IP/Bandwidth_throttling.aspx これは、単一の接続のスリープ時間を計算します。

複数の接続に対してこれを行う最善の方法を知りたいです。

上記の ThrottledStream を使用して、帯域幅 (たとえば 2MB/秒) を接続間で均等に分割することは正しくありません。3 つの非常に低速な接続と 1 つの非常に高速な接続がある場合、それらはすべて 512kb/秒に制限されるため、高速のものは 512kb/秒を超えず、他の 3 つもそれを達成しません。

私が考える好ましい解決策は、最速の接続のみを制限して、低速の接続が最適に使用されるようにすることです。

誰かがこれ、サンプルコードまたはアドバイスの経験がありますか?

4

5 に答える 5

3

私の場合、帯域幅の要件をN個に分割することから始めます。ここで、Nは同時接続の数です。次に、各接続のパフォーマンスを監視し、必要に応じて調整します。まず、設定した最高​​速度で動作している接続を特定します。これらの接続は、必要に応じて速度を上げるための候補になります。次に、私が設定した帯域幅制限を満たしていない接続(未達成者)を特定します。そうすれば、後者のグループの不足分を簡単に要約できます。その数を取得し、最高速度で実行されている接続の数で割って調整します。

許容される合計帯域幅:100KB/秒
接続:5
接続ごとの初期制限:20KB/秒

実績:
接続1:10KB/秒
接続2:5KB/秒
接続3:20KB/秒
接続3:20KB/秒
接続3:20KB/秒

ショートトータル:15KB/秒

新しい接続ごとの制限:
接続1:10KB/秒
接続2:5KB/秒
接続3:25KB/秒
接続3:25KB/秒
接続3:25KB/秒

次に、これを一定の間隔で監視します。

于 2009-05-18T20:17:31.723 に答える
2

頭のてっぺんから、(おそらく移動平均比較を介して) コレクターが適切にスリープ状態で、各ストリームから順次プルされるコレクター オブジェクト/クラスを取得します。これにより、ストリームのバランスが取れて、一方が他方よりも遅い場合に帯域幅制限を完全に達成できるようになります...プルするためにポーリングし、それが空であることを確認し、スリープする前に次のストリームをプルします。

コレクターは、取得された集約データ/時間によって制限されるため、適切なクライアント側の帯域幅が得られます。

于 2009-05-18T20:08:27.327 に答える
0

少し調整するだけで、最初の投稿でリンクしたクラスを使用でき、スロットルとリセットを静的クラスに配置できます。

于 2011-04-22T04:02:15.457 に答える
0

上記の短い合計は実際には 25kb/秒ですが、接続をグループに分ける代わりに、速度で並べ替えてそれらをループします。総帯域幅から始めて、新しい帯域幅を (残りの帯域幅 / 残りの数) に設定します。これにより、5k および 10k 接続が高速化した場合に備えて、接続の制限が維持されます。割り当てられた帯域幅を超える可能性がありますが、それを修正します。

List<Connection> connections = GetConnections();
connections.Sort(); // sorts by Speed
bandwidth = 100000;
for (int i = 0; i < connections.Count; i++)
{
    Connection cnn = connections[i];
    cnn.SpeedLimit = bandwidth / (connections.Count - i);
    bandwidth -= Math.Min(cnn.Speed, cnn.SpeedLimit);
}

(start with all connections SpeedLimit set to 20000 bytes/sec)

Speed   bandwidth SpeedLimit
5000    100000  20000
10000   95000   23750
20000   85000   28333
20000   65000   32500
20000   45000   45000

接続の合計速度制限は 149583 であるため、低速のものの速度が上がると制限を超える可能性がありますが、毎秒制限を調整すると、かなり近くなるはずです。

接続速度は 5000、10000、28333、21000、45000 に変化するため、実際には 109,333 バイトをダウンロードしましたが、再度調整します。45k を除くすべての接続が可能な限界に達しました。

Speed   bandwidth SpeedLimit
5000    100000  20000
10000   95000   23750
21000   85000   28333
28333   64000   32000
45000   35667   35667 

新しい速度は、正確に 5000、10000、21000、28333、35667、100k になります。

Speed   bandwidth SpeedLimit
5000    100000  20000
10000   95000   23750
21000   85000   28333
28333   64000   32000
35667   35667   35667

ここで、5k の接続速度が最大 20k であると仮定します。

Speed   bandwidth SpeedLimit
10000   100000  20000
20000   90000   22500
21000   70000   23333
28333   49000   24500
35667   20667   20667
于 2009-07-11T22:10:33.763 に答える
0

私も同じ問題を抱えてる。私は VS2010 Pro を試しています。複数のファイル (10 ~ 50) を同時にダウンロードする小さなホーム プロジェクトを作成しました。それらすべての帯域幅を制限したいと考えています。この投稿を見つけましたが、解決策が実際には見えないので、自分で試しました。

私がしたことは、非常にシンプルに構築された DownloadLimiter クラスを作成したことです。Downloader がチャンクをダウンロードするたびに (InputStream.Read() の直前など)、DownloadLimiter に帯域幅を要求する必要があります。たとえば、50 000 (bytesPerSecond など) の制限を保持する変数と、ask() が処理されて返されるたびに減少する availableBandwidthPerSecond があります。

また、1000 ミリ秒ごとに availableBandwidthPerSecond を制限にリセットするタイマーも含まれています。

ask() メソッドはロックされているため、現在使用可能な帯域幅が残っていない場合は、タイマーが使用可能な帯域幅をリセットするまでループしてしばらくスリープします。

ただし、完全に機能します。問題があります。かなり高速な接続 (100 メガビット) があり、制限を 200kb に設定したとします。1 つのファイルを (同様の高速接続から) ダウンロードすると、x ミリ秒の間 100 メガビットでピークに達し、利用可能な帯域幅がリセットされるまで待機します。そして、これはファイルが完了するまで続きます。平均ダウンロード速度はかなり均一ですが、帯域幅のグラフを見ると、1 秒ごとにピークがあります。ThrottledStream への投稿されたリンクは、ピーキングと同じように機能すると思います。

上記のテキストが役に立ったかどうかはわかりません...興味のある方は、コードをどこかに投稿して読んでください。私はまだスレッド化に慣れていないので、(必要に応じて) いくつかの最適化も行うとよいでしょう。:)

于 2010-04-20T22:25:12.327 に答える