
No.1ベストアンサー
- 回答日時:
先日速度制限しながら送信するプログラムを仕事で書いたので、
ソース貼れませんがロジックだけ返答してみます。
(x)bpsで(y)byte送信するのにかかる時間は(z)秒とします。
1.現在時刻取得
2.send()でyバイト送信
3.現在時刻を取得し、1.の値を引いて送信所要時間を算出
4.sleep(z-3.の値)
5.1へ
上記のような送信ループを実装しました。
実際には0.??秒になるのでsleep()ではなくusleep()を呼びました。
送信後、余った時間は寝てもらうというわけです。
質問者様の環境が書かれていないのでアレですが、
私はLinuxで実装したので、現在時刻の取得には
gettimeofday()を使いました。
蓄積誤差が発生するので、なるべく分解度の高い時刻やsleepを
使うといいと思います。
# たとえばtime()は秒を返すのでこういうケースでは使えません
若干でも参考になれば幸いです。
この回答への補足
有難うございました。ロジックだけでも助かります。
ちなみに、私はWindows環境で作成しています。
なにか注意事項や補足がありましたら、よろしくお願いいたします。
あと、「2.send()でyバイト送信」とありますが、これはサイズの大きなファイルでも(分割などはせず)とりあえず一気に送って、送信にかかる時間(何十秒とか何分とか)だけ待つ、ということでしょうか?
No.4
- 回答日時:
> よろしければ、もう少し説明していただけないでしょうか?
では、実際に計算してみると分かるでしょうか。
前出の計算式を使って、10Mずつ送信するケースを考えると、
1Mbpsに制限したい場合、10Mbyte(10000000byte)送信するのに必要な時間は
x = 1000000(bps)
y = 10000000(byte)
z = 10000000 * 8 / 1000000 = 80(秒)
となります。
実際には10Mbyteを10秒で送信してしまった場合、70秒待てば
実質1Mbps相当ですよね、長い目でみれば。
しかしながら、最初の1秒間に注目してみると、全力で送信してますので
1Mbpsになったとは言えません。
1000byteずつ送信とsleepをくりかえした場合、最初の1秒に注目しても
だいたい1Mbps程度となります。
小刻みに送ったり休んだりしてるので。
通信速度計りながら実際にやってみると分かりますよ。
> これは、fflush()が「コールした瞬間、バッファのパケットが発射される」ように(私が)実装すれば、という認識で正しいでしょうか?
> それとも、fflush()が「コールした瞬間、バッファのパケットが発射される」ように実装されていれば、でしょうか?
曖昧な表現になってしまってすみません。
後者が正解です。
Posixではバッファをクリアする関数が用意されてるので、それを使ってみるのが正解かな、と
思ったもので。
参考までにfflush()のmanを貼っておきますね。
> fflush - ストリームの内容を強制的に出力(フラッシュ)する
>
> 書式
> #include <stdio.h>
>
> int fflush(FILE *stream);
>
> 説明
> fflush() 関数は、ユーザー空間でバッファリングされているすべてのデータを
> 与えられた出力に書き出す (フラッシュする)。あるいはストリーム stream の
> 下 位にある書き込み関数を用いてこのストリームを更新する。ストリームは開
> いた状態のままであり、この関数によって何の影響も受けない。
>
この回答への補足
有難うございました。
>実際には10Mbyteを10秒で送信してしまった場合、70秒待てば
>実質1Mbps相当ですよね、長い目でみれば。
>しかしながら、最初の1秒間に注目してみると、全力で送信してますので
>1Mbpsになったとは言えません。
平均1Mbpsだからといって、実際の送信状態が一定になっているとは限らない、ということですね。
No.3
- 回答日時:
> ところで、「1000byteに深い意味はないですが、・・・」とのことですが、この値はどのように決めたらよいのでしょう?
> 一般的にこのくらいの値を使うことが多い、とか、こういう計算で求める、とか、帯域に対して何%、とか、あるのでしょうか?
きっと質問されると思ってました(^^;
これは正直私も論理的にどうっていうものはありません。
一つの考え方として、一般的にパケットサイズは1500byteです。
TCPヘッダを除くと1460byteですので、それより小さめがいいかなと
考えることができます。
ただし、send()時すぐに送信されるのか、バッファリングして適当なタイミングで
まとめて送信するのかなどがネットワークスタック(TCP/IPドライバ)の実装次第で変わります。
ようはsend()一発とパケット1つが対応する保証がないので、
上のように考えても意味がないとも言えます。
実際に動作させる環境で様子をみて、期待と違う動きをしていたら
「この辺の仕様が思ってるのと違うのかな?」と思いを馳せつつ
送信サイズをチューンするって感じですかね。
Posix関数にはfflush()というバッファをクリアする関数があって、
これをコールした瞬間、バッファのパケットが発射される実装のものも
あります。
一般的な数値も私は分からないです。
ただ、例えば10Mbyteごとにsleep()では、送信の時間と待ち時間が
それぞれ長くなりすぎて、ネットワーク負荷が矩形波のように
なってしまうことは想像できるかと思います。
そうならなさそうな数値ってことで、パケットサイズよりちょっと小さい
1000くらいとしてみました。
1460送ってfflush()が正解かもしれませんね。
割と適当でも動いてしまったので、それ以上私は調べてないというのが
本音のところです。
すみません。
この回答への補足
何度もお答えいただき、本当に有難うございます。
いくら探しても、これぞという値の決め方が見つからなかった理由がちょっとわかった気がします。
ですが、まだちょっとよくわからないところがあります。
よろしければ、もう少しお付き合いください。
>ただ、例えば10Mbyteごとにsleep()では、送信の時間と待ち時間が
>それぞれ長くなりすぎて、ネットワーク負荷が矩形波のように
>なってしまうことは想像できるかと思います。
すみませんが、ここがちょっとわかりません。よろしければ、もう少し説明していただけないでしょうか?
(一気に大きなサイズを送り出したら、送信中は帯域を占有してしまうであろうことまではわかるのですが・・・)
不勉強で申しわけありません。
>1460送ってfflush()が正解かもしれませんね。
これは、fflush()が「コールした瞬間、バッファのパケットが発射される」ように(私が)実装すれば、という認識で正しいでしょうか?
それとも、fflush()が「コールした瞬間、バッファのパケットが発射される」ように実装されていれば、でしょうか?
こちらも不勉強で申しわけありません。
No.2
- 回答日時:
1です。
> とりあえず一気に送って、送信にかかる時間(何十秒とか何分とか)だけ待つ、ということでしょうか?
それだとbps的にばらつきが出ますので、1000byte程度ずつ
送ります。
(1000byteに深い意味はないですが、小さめということで)
たとえば1Mbpsに制限したい場合、1000byte送信するのに必要な時間は
x = 1000000(bps)
y = 1000(byte)
z = 1000 * 8 / 1000000 = 0.008(秒)
となりますので、0.008秒で送信したいわけです。
ここで、たとえば送信が0.005秒で終わってしまった場合、
0.003秒のsleep()で調整してやると、転送レートが
だいたい1Mbpsとなります。
コレをファイル転送が終わるまでループで処理すると、
指定速度でファイルが転送されていきます。
Windowsでの注意点ですが、確かWin32APIのSleep()はあんまり
分解能が高くないので(参考URL参照)、送信サイズをもう少し
大きくするなどの工夫がいると思います。
過去実験した個人的な数値では、50ミリ秒以下のSleep()は
全て50ミリ秒待たされてしまいました。Windows2000での実験だったと
思うので、XPやVistaでどうなってるかは分りません。
作ってみたけど妙に通信速度が遅い、といったときには
この辺を疑ってみてください。
参考URL:http://oshiete1.goo.ne.jp/qa1796385.html
この回答への補足
有難うございました。
やり方は、一度にドカッと、ではなく、一定量(少量)を送り続ける、なのですね。
ところで、「1000byteに深い意味はないですが、・・・」とのことですが、この値はどのように決めたらよいのでしょう?
一般的にこのくらいの値を使うことが多い、とか、こういう計算で求める、とか、帯域に対して何%、とか、あるのでしょうか?
たびたびですみませんが、よろしかったらご教授願います。
お探しのQ&Aが見つからない時は、教えて!gooで質問しましょう!
似たような質問が見つかりました
- ネットワーク OSI参照モデルの各層の役割がわかりません。 3 2023/04/21 21:12
- Visual Basic(VBA) エクセルのマクロについて教えてください。 1 2023/08/03 12:30
- ダイヤルアップ Raspberry Piでアナログモデム経由で音声再生 1 2022/05/20 18:01
- USBメモリー・SDカード・フラッシュメモリー 銀行が振込データの受け渡しに未だにFDを使っている理由は「FDDがAドライブ固定だから」って本当? 11 2022/06/02 03:53
- その他(コンピューター・テクノロジー) 「プロトコル」の定義について 5 2023/04/16 13:13
- Visual Basic(VBA) 3つのプロシージャをまとめたら実行時エラー発生で対応不能 6 2022/05/17 01:47
- ガラケー・PHS 携帯電話の居場所信号の発信タイミング 3 2022/07/27 14:39
- iPhone(アイフォーン) 新しいiPhoneに変えました。 古い携帯から電話帳やLINE、写真全てデータを移しました。 古い携 2 2023/01/31 00:23
- HTML・CSS GETをPOSTに変更したところ 送信 不能です。 1 2022/04/10 17:31
- その他(Microsoft Office) マクロVBAについて 1 2022/09/06 18:12
関連するカテゴリからQ&Aを探す
おすすめ情報
デイリーランキングこのカテゴリの人気デイリーQ&Aランキング
-
Googleフォームを回答したか確...
-
BASP21のSendMailとSendMailEx...
-
お問い合わせフォームから送信...
-
フォームを再送信しますか?
-
SendmailでHTML形式のメールを...
-
ソケットで通信するデータの帯...
-
c# メールが送信できたか確認
-
sendmailでメール送信ができない
-
文字のフォントの色で分岐する...
-
ビジネスメールの敬称
-
エクセルVBA テキストボックス...
-
数字以外の入力をエラーにする...
-
Excel-VBAでInputBox+Pulldown...
-
VBAでInputBoxの再入力をさせる...
-
初歩的な事だと思います。 Sub...
-
テキストボックスの番号を使っ...
-
入力フォームの値をQRコードで...
-
DATE型変数を初期化する方法
-
InputBoxでキャンセルボタンを...
-
VBA R1C1形式で変数の入力について
マンスリーランキングこのカテゴリの人気マンスリーQ&Aランキング
-
Googleフォームを回答したか確...
-
お問い合わせフォームから送信...
-
フォームを再送信しますか?
-
ソケットで通信するデータの帯...
-
メールフォームで送信すると「...
-
c# メールが送信できたか確認
-
ホームページビルダーのメール...
-
VB6で、Bsmtp.dllを使って、メ...
-
sendmailでメール送信ができない
-
Accessでメール一括送信ソフ...
-
Safariで「本当にこのフォーム...
-
BASP21のSendMailとSendMailEx...
-
HP作成について質問です
-
VBで添付ファイル付きのメール...
-
postmail(UTF-8)でメールが文字...
-
VB.NETからGmail経由でメールを...
-
Message ID
-
検索cgi
-
FLASHからアプリケーションの呼...
-
VB.NET(2005)の"SerialPort" ...
おすすめ情報