Cのソケット接続の帯域幅をどのように調整しますか?
-
04-07-2019 - |
質問
BSDソケットを使用してクライアントサーバーアプリケーションを作成しています。バックグラウンドで実行し、データを継続的に転送する必要がありますが、通常の使用からネットワークインターフェイスの帯域幅を独占することはできません。インターフェイスの速度に応じて、この接続を特定の最大転送速度に調整する必要があります。
これをプログラムで達成する最良の方法は何ですか?
解決
各転送後に一定の1秒間スリープする場合の問題は、ネットワークパフォーマンスが不安定になることです。
BandwidthMaxThresholdを目的の帯域幅のしきい値にします。
TransferRateを現在の接続の転送速度にします。
その後...
TransferRateを検出した場合> BandwidthMaxThresholdを実行すると、SleepTime = 1 + SleepTime * 1.02(スリープ時間を2%増加)
各ネットワーク操作の前後に スリープ(スリープ時間)
TransferRateがBandwidthMaxThresholdよりもかなり低いことを検出した場合、SleepTimeを減らすことができます。あるいは、SleepTimeを常に時間とともに減衰/減少させることもできます。最終的に、SleepTimeは再び0になります。
2%の増加の代わりに、TransferRate-BandwidthMaxThresholdの差を直線的に大きく増加させることもできます。
このソリューションは、ユーザーのネットワークが希望するほど高くない場合にスリープしないため、優れています。
他のヒント
最良の方法は、トークンバケットを使用することです。
パケットを埋めるのに十分なトークンがある場合のみ送信します(1460バイトで十分です)、または受信側の場合、十分なトークンがある場合にのみソケットから読み取ります。少しの簡単な計算により、十分なトークンを得るまでにどれだけの時間待たなければならないかがわかりますので、その時間だけスリープすることができますほとんどのオペレーティングシステムは、要求よりも長くプロセスをスリープ状態にできるため、スリープしました。
バーストのサイズを制御するには、保持できるトークンの最大量を制限します。十分な量は1秒分のトークンになります。
trickle で幸運を祈りました。変更せずに任意のユーザー空間アプリケーションを調整できるため、すばらしいです。帯域幅の計算を行う独自のsend / recvラッパー関数をプリロードすることで機能します。
私が見つけた最大の欠点は、有限の帯域幅を共有したい複数のアプリケーションを調整するのが難しいことです。 「トリクル」役立ちますが、私はそれが複雑であることがわかりました。
2017年の更新:トリクルが https://github.com/mariusae/trickleに移動したようです