- ベストアンサー
writeで止まります
C++でクライアントとサーバを作ってみました。クライアントが送信したものをそのまま、サーバが返す処理です。クライアントから512byteを10000件送信しようとしたのですが、1850件までwriteしてを使っているのですが、512byteのデータを170件ほど書き込んだ段階でwriteでストップし、サーバ側は802件受信して送り返そうとした段階でwriteでストップしてしまいます。 SO_SNDBUFとSO_RCVBUFのサイズは1000000000ほどに設定しています。何が詰まってしまっているような感じですが、何が悪いか不明です。御教授ください。
- みんなの回答 (7)
- 専門家の回答
質問者が選んだベストアンサー
>>ふつうはどれくらいのサイズで設定して使うものなんでしょうか。 バッファサイズは、通常はオプション指定しないと思いますよ、デフォルトまかせ。ソケット関連のオプションて指定しても、無視ってものもありましたし(現在は知りませんが)。現実問題として、サーバとクライアント間には、ルータなどがいくつか入るわけですし、送受信のパケットがうまく処理されたか確認しながら処理を進めるので、あまり大きくしても意味ないってことでしょう。 それに、ちょっと大きなシステムなら、クライアントからの同時接続が100以上あったりします。1つのソケットにそんなに大きなバッファを割り当てていたら、もったいない気がします。
その他の回答 (6)
- lv4u
- ベストアンサー率27% (1862/6715)
>>クライアント側では10000回送り出してからサーバのデータを受信し始めるので、 これはまずいと思います。通常は、送信と受信を並行して行なうようなプログラムにします。10000回も送信したら、TCP/IPのバッファはパンクするでしょう。停止して当然です。 送受信をスレッドにするか、selectを使うコーディングをやらないとまずいですよ。
お礼
確かにそうですよね。そうすべきだと思います。ただ、素人の疑問なんですが、TCP/IPのバッファというのはそんなものなんでしょうか 512byte*170回ぐらいで止まっていますから870kbyteぐらいですからちいさなものなんですね。 変更は出来そうですが。ふつうはどれくらいのサイズで設定して使うものなんでしょうか。
- lv4u
- ベストアンサー率27% (1862/6715)
送信(write)が512byte単位で送信していても、TCP/IPはそのパケットサイズでやりとりするとは限りません。 受信側(read)には512byteが1パケで到着するかもしれないし、極端な場合、1byteが512個のパケットで届くかもしれません。 イメージ的には、バイト列の垂れ流しが届くって想定してプログラムを作ると改善するかも? あと、大量データを高速でクライアント側から送信すると、その結果、クライアント側の受信バッファが、詰まった状態になる可能性もありますね。そうなれば、サーバ側の送信バッファが詰まり、そして連鎖的にサーバの受信バッファも詰まるため、クライアント側が送信できなくなります。 なかなか、この手の問題の解析って難しいですが、print文やsleep文を入れるとか、サーバ、クライアント側の1回の受信バイト数を表示させてみれば、原因がわかると思います。
お礼
お世話になります。 わかりやすい説明ありがとうございます。 バイト列のwrite/readは意識した作りにはなっています。 (read/writeの細切れ対応) >あと、大量データを高速でクライアント側から送信すると、その結果、 >クライアント側の受信バッファが、詰まった状態になる可能性も >ありますね。そうなれば、サーバ側の送信バッファが詰まり、 >そして連鎖的にサーバの受信バッファも詰まるため、 >クライアント側が送信できなくなります。 まさにそのような状態です。 クライアント側では10000回送り出してからサーバのデータを受信し始めるので、1回ごとにサーバ側では応答を返しているのですが、(サーバ側ではreadとwriteでプラスマイナスゼロ)クライアントの送りだす分がすべて溜まってしまっているように見えます。 それでsetsockoptでバッファのサイズを大き目に調整したのですが、確かに送信回数は増えるのですが、10000回には達していません。
もしかして、 data=送受信バッファ for (unsigned int i=0;i<5120000;i+=512) { sendto (・・,data,i,・・,・・,・・); } のようなアルゴリスム処理をしてるのではないでしょうか? そうであれば、 sendto (・・,data,512,・・,・・,・・) のようにカウンタ数を送受信ブロック数にする必要がありますが。
お礼
お世話になっています。 送信(write)は512byte単位で送っていますのでその点は問題ないと思われます。
- Wr5
- ベストアンサー率53% (2173/4061)
> バッファが大きすぎるとだめというのがうまく理解できません。なぜだか教えていただけますか? ローカル変数はたいていスタック領域に確保する。 という実装が多いです。 そして、このスタック領域のサイズはそれほど多くありません。 (VCだとデフォルトが1M程度の様です。64kなんてのもあるようですが) となると、ローカル変数に使える領域は限られることになります。 ヒープから取得(newやmalloc()等)か、グローバル変数にすればスタックを食いつぶすともないでしょう。 ヒープの場合は開放忘れると大変ですが。
補足
お世話になっています。 いまいち理解できない状態で情けないのですが、 念のためですがバッファとはsetsockoptで設定するサイズのことですが認識はあっていますでしょうか。
SAYKA さん、ビンゴかもしれませんよ。 本来は、512byteだけを確保して512バイトデータを10000回送信するものを、 ようは 512*10000=5120000 のバッファを一括確保してる 典型的な例ですね。 送信データ、1伝送分(伝送効率は抜き)データのみ確保すれば いいのではないでしょうか?
お礼
回答ありがとうございます。SAYKAさんへのお礼にも書いたとおりの理解度です。よろしくお願いします。念のためですがバッファとはsetsockoptで設定するサイズのことですが認識はあっていますでしょうか。
バッファがでっかすぎるとかいうオチだったりして
お礼
早速の返事をありがとうございます。バッファが大きすぎるとだめというのがうまく理解できません。なぜだか教えていただけますか?
お礼
ご回答ありがとうございます。参考までにデフォルトでどれくらいのサイズかは調べてみます。ありがとうございました。