2009-05-18 8 views
4

Ich schreibe eine App in C#, die gleichzeitig (in verschiedenen Threads) mit mehreren Verbindungen zu mehreren Servern, und ich möchte in der Lage sein, die verwendeten zu begrenzen Bandbreite.Begrenzung/Drosselung der Bandbreite mit * multiple * Verbindungen

Für eine einzelne Verbindung wäre die Lösung einfach; Ich würde die hier veröffentlichte Lösung verwenden: http://www.codeproject.com/KB/IP/Bandwidth_throttling.aspx , die eine Ruhezeit für die einzelne Verbindung berechnet.

Ich würde gerne wissen, was der beste Weg ist, dies für mehrere Verbindungen zu tun.

Verwenden Sie den oben genannten ThrottledStream und Dividieren der Bandbreite (sagen 2MB/sec) gleichmäßig unter den Verbindungen ist nicht richtig, wenn ich 3 sehr langsame Verbindungen und 1 sehr schnelle hätte sie alle auf 512kb begrenzt werden/sec, so dass der schnelle nicht über 512kb/sec geht und die anderen 3 würden das nicht machen.

Die bevorzugte Lösung, denke ich, ist es, nur die schnellste (n) Verbindung (en) zu beschließen, damit die langsameren Verbindungen optimal genutzt werden.

Hat jemand Erfahrung damit, Beispielcode oder einen Ratschlag?

Antwort

2

Von meinem Kopf weg, würde ich ein Sammlerobjekt/Klasse bekommen, die sequentiell aus jedem Strom zog mit dem Kollektor schlafen wie geeignet (wahrscheinlich über einen gleitenden Durchschnitt Vergleich). Dadurch werden Ihre Streams ausgeglichen, damit das volle Bandbreitenlimit erreicht wird, wenn einer langsamer als der andere ist ... Sie werden abfragen, um ihn zu ziehen, finden ihn leer und ziehen den nächsten Stream vor dem Schlafen.

Da Ihr Kollektor durch aggregierte Daten gezogen/Zeit begrenzt ist, erhalten Sie die richtige Client-Seite Bandbreite.

3

Wenn ich es wäre, würde ich zuerst die Bandbreite Anforderung in N Stücke zerhacken, wobei N die Anzahl der gleichzeitigen Verbindungen ist. Als Nächstes würde ich die Leistung jeder Verbindung überwachen und bei Bedarf Anpassungen vornehmen. Zuerst würde ich alle Verbindungen identifizieren, die mit der von mir eingestellten Höchstgeschwindigkeit arbeiten. Diese Verbindungen wären Kandidaten für erhöhte Geschwindigkeiten, wenn Bedarf besteht. Als nächstes würde ich diejenigen Verbindungen identifizieren, die die von mir angegebenen Bandbreitenbeschränkungen nicht erfüllen (die Underachievers). Es wäre dann leicht, die Fehlschläge der letzteren Gruppe zusammenzufassen. Sie würden diese Nummer nehmen, dividieren durch die Anzahl der Verbindungen mit Höchstgeschwindigkeit und nehmen die Anpassungen vor.

 
Total Bandwidth Allowed: 100KB/Sec 
Connections : 5 
Initial per-connection limit: 20KB/sec 

Actual Results: 
Connection 1: 10KB/sec 
Connection 2: 5KB/sec 
Connection 3: 20KB/sec 
Connection 3: 20KB/sec 
Connection 3: 20KB/sec 

Total Short: 15KB/sec 

New Per-Connection Limits: 
Connection 1: 10KB/sec 
Connection 2: 5KB/sec 
Connection 3: 25KB/sec 
Connection 3: 25KB/sec 
Connection 3: 25KB/sec 

Sie würden dann in einigen Abständen überwachen.

0

Die gesamte kurze oben ist wirklich 25kb/sec, aber anstatt die Verbindungen in Gruppen zu trennen, würde ich nach Geschwindigkeit und Schleife durch sie sortieren. Beginnen Sie mit der Gesamtbandbreite und legen Sie die neue Bandbreite auf (verbleibende Bandbreite/verbleibende Anzahl) fest. Dies würde die Grenzen für die 5k und 10k Verbindungen halten, falls sie schneller werden. Sie könnten über Ihre zugewiesene Bandbreite gehen, aber Sie würden es korrigieren.

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 

Die Gesamtgeschwindigkeitsbegrenzung für Verbindungen ist 149.583, so dass Sie über Ihr Limit gehen könnten, wenn die langsame Beschleunigung, aber wenn man die Grenzen anpassen jede Sekunde sollte es ziemlich nahe sein.

Die Verbindungen Geschwindigkeiten ändern sich zu: 5000, 10000, 28333, 21000, 45000, so haben wir tatsächlich 109.333 Bytes heruntergeladen, aber wir werden wieder anpassen.Alle Verbindungen mit Ausnahme des 45k einen haben ihre möglichen Grenzen erreicht:

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

Die neuen Geschwindigkeiten 5000 sein wird, 10000, 21000, 28333, 35667, 100k genau

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

Lassen Sie uns nun die 5k Verbindungsgeschwindigkeiten annehmen bis zu 20k:

Speed bandwidth SpeedLimit 
10000 100000 20000 
20000 90000 22500 
21000 70000 23333 
28333 49000 24500 
35667 20667 20667 
0

Ich habe das gleiche Problem. Ich probiere VS2010 Pro aus und ich habe ein kleines Heimprojekt gemacht, bei dem ich mehrere Dateien (10-50) gleichzeitig herunterlade und ich möchte die Bandbreite für alle begrenzen. Ich habe diesen Beitrag gefunden, aber ich kann keine Lösung sehen, also habe ich es selbst versucht.

Was ich getan habe, war, ich habe eine DownloadLimiter-Klasse erstellt, die wirklich einfach aufgebaut ist. Jedes Mal, wenn ein Downloader einen Chunk herunterladen möchte (etwa vor InputStream.Read()), muss er den DownloadLimiter nach Bandbreite fragen. Es hat eine Variable, die eine Beschränkung enthält, Beispiel 50 000 (wie BytesPerSekunde) und availableBandwidthPerSecond, die abnimmt, wenn jedes ask() verarbeitet und zurückgegeben wird.

Es enthält auch einen Timer, der die verfügbarenBandwidthPerSecond jeweils 1000ms auf die Begrenzung zurücksetzt.

Die ask() -Methode ist gesperrt. Wenn derzeit keine verfügbare Bandbreite verfügbar ist, wird sie nur für eine Weile wiederholt, bis der Timer die verfügbare Bandbreite zurückgesetzt hat.

Es funktioniert jedoch perfekt. Es gibt ein Problem. Nehmen wir an, Sie haben eine ziemlich schnelle Verbindung (100 Megabit) und setzen das Limit auf 200kb. Wenn Sie eine Datei herunterladen (von einer ähnlichen schnellen Verbindung), werden Sie bei 100megabit für x Millisekunden Höchstwert erreichen, dann wird es warten, bis die verfügbare Bandbreite zurückgesetzt wurde. Und dies wird fortgesetzt, bis die Datei abgeschlossen ist. Die durchschnittliche Download-Geschwindigkeit ist ziemlich gleichmäßig, aber wenn Sie ein Bandbreiten-Diagramm betrachten, wird es jede Sekunde Peaks haben. Ich vermute, dass der gepostete Link zu ThrottledStream genauso funktioniert wie Peaking.

Ich weiß nicht, ob der obige Text Ihnen geholfen hat ... Wenn irgendjemand interessiert ist, kann ich den Code irgendwo für Sie lesen. Wäre schön mit einigen Optimierungen (wenn du willst), da ich mit Threading noch nicht so vertraut bin. :)

+0

Hallo DavidMB, Macht es Ihnen posten ** DownloadLimiter Klasse **? Dank Jeff in Seattle –

0

Mit ein wenig zwicken können Sie die Klasse verwenden, die Sie in Ihrem ersten Beitrag verknüpft haben, setzen Sie das Gas und Reset in eine statische Klasse.