2008-10-25 4 views
21

Ich schreibe eine Client-Server-App mit BSD-Sockets. Es muss im Hintergrund laufen und kontinuierlich Daten übertragen, kann aber die Bandbreite der Netzwerkschnittstelle nicht aus der normalen Nutzung herausholen. Abhängig von der Geschwindigkeit der Schnittstelle muss ich diese Verbindung auf eine bestimmte maximale Übertragungsrate drosseln.Wie drosseln Sie die Bandbreite einer Socket-Verbindung in C?

Was ist der beste Weg, dies programmatisch zu erreichen?

+0

Stellen Sie die Socket-Empfangspuffergröße auf das gewünschte Produkt mit Bandbreitenverzögerung ein. – EJP

Antwort

17

Das Problem mit einer konstanten Menge von 1 Sekunde nach jeder Übertragung ist, dass Sie abgehackte Netzwerkleistung haben.

Lassen Sie BandwidthMaxThreshold den gewünschten Bandbreitenschwellenwert.

Lassen Sie TransferRate die aktuelle Übertragungsrate der Verbindung sein.

Then ...

Wenn Sie Ihren TRANSFER erkennen> BandwidthMaxThreshold dann tun Sie einen Sleeptime = 1 + Sleeptime * 1,02 (Erhöhung Schlafzeit um 2%)

Vor oder nach jedem Netzwerkbetrieb eines tun Sleep (SleepTime)

Wenn Sie feststellen, dass Ihr TransferRate viel niedriger als Ihr BandwidthMaxThreshold ist, können Sie SleepTime verringern. Alternativ könntest du deine SleepTime im Laufe der Zeit immer verringern/verringern. Schließlich wird Ihre SleepTime wieder 0 erreichen.

Statt einer Erhöhung von 2% können Sie auch linear den Unterschied zwischen TransferRate - BandwidthMaxThreshold erhöhen.

Diese Lösung ist gut, weil Sie nicht schlafen müssen, wenn das Netzwerk des Benutzers nicht so hoch ist, wie Sie es möchten.

+0

@Brian: Warum ist das '1 +' notwendig? Will nicht SleepTime = 1.02 * SleepTime selbst den Wert um 2% erhöhen? – sundar

+2

Ich habe es gerade hinzugefügt, damit SleepTime, wenn es 0 erreicht, wieder wachsen kann. Auch damit es immer um mindestens 1 anwächst, wenn es wachsen muss. –

+0

Wenn das Protokoll Bestätigungen verwendet, dann könnte die Verzögerung vor dem Empfang einer Antwort auch verwendet werden, um eine Ende-zu-Ende-Pipeline-Verzögerung bereitzustellen und die Rate vorzuschlagen, mit der Nachrichten zu übertragen sind. Dies würde eine adaptive Lösung bereitstellen, die eine Selbstabstimmung in mehreren Installationen erlauben würde. – Pekka

6

Ich hatte viel Glück mit trickle. Es ist cool, weil es beliebige User-Space-Anwendungen ohne Änderung drosseln kann. Es funktioniert, indem es seine eigenen Send/Recv-Wrapper-Funktionen vorlädt, die die Bandbreitenberechnung für Sie durchführen.

Der größte Nachteil, den ich fand, war, dass es schwierig ist, mehrere Anwendungen zu koordinieren, die endliche Bandbreite teilen möchten. "tröpfelte" hilft, aber ich fand es kompliziert.

-Update im Jahr 2017: es sieht aus wie Rinnsal https://github.com/mariusae/trickle bewegte

12

Der beste Weg, um ein token bucket zu verwenden wäre.

Senden Sie nur, wenn Sie genug Tokens haben, um ein Paket zu füllen (1460 Bytes wären eine gute Menge), oder wenn Sie die Empfangsseite sind, lesen Sie nur dann aus dem Socket, wenn Sie genug Tokens haben; Ein wenig einfache Mathematik wird Ihnen sagen, wie lange Sie warten müssen, bis Sie genug Token haben, so dass Sie diese Zeit schlafen können (seien Sie vorsichtig, um zu berechnen, wie viele Token Sie durch wie viel tatsächlich geschlafen haben, da am meisten Betrieb Systeme können Ihren Prozess länger speichern als Sie gefragt haben).

Um die Größe der Bursts zu begrenzen, begrenzen Sie die maximale Anzahl an Tokens, die Sie haben können; Eine gute Menge könnte eine Sekunde wert sein.