こんにちはゲストさん。会員登録(無料)して質問・回答してみよう!

解決済みの質問

ソケットを使った通信

いつ発生するか分からない128バイト程度のデータをできるだけ早く(1秒以内)インターネットの向こう側に点在している500台程度の端末に確実に送りたいのですが、どういう方法があるでしょうか?サーバのOSはUNIXを想定しています。
500台の端末から1台のサーバにTCPセッションを張ったまま(forkして子プロセスにするなど)にして、このようなことを実現するのは可能でしょうか?

投稿日時 - 2005-03-04 18:19:37

QNo.1250465

すぐに回答ほしいです

質問者が選んだベストアンサー

No.4,5 の MiracleCat 再びです。
>・サーバでパッシブオープンしたソケットに端末からアクティブオープン(端末はいつネットに
>接続されるか分からないので)する場合、ご回答頂いた一つのプロセスで実現する方法はありま
>すでしょうか?

この辺りは socket の基本ですが、bind() でポート番号を固定したソケットを listen() 状態にして、select() に対して READ で待ちうけすると、端末が接続して来た時に select() から制御が戻るのですかさず accept() して、出てきたソケットを片っ端から READ で select() にぶら下げます。
端末からデータが来たり切断されたら select() が抜けてくるので処理してあげます。
問題の128バイト程度のデータがどこから来るか知りませんが、それもソケット経由で来るのならこの1つの select() の下にぶら下げて待ち合わせして、データが届いたらその時点でオープンしている全ソケットに非同期で片っ端から書き込むループを回すというような感じです。
非同期書き込みするのは、万が一にも制御ループをブロックさせないためです。

>・仮に、端末の台数だけプロセスをforkした場合、メモリ等のリソースはそこそこあるとして、
>一つ目のプロセスがデータを送出す時刻からから500個目のプロセスがデータを送出す時刻
>までの遅延はどんなものでしょうか?回線は十分太い(100Mbps)とします。

すみません、それだけ大量のプロセスを上げての処理ってやった事が無いので何とも言えませんが、プロセススイッチが比較的高速なUNIXの場合、全プロセスがスワップ落ちせずオンメモリでいればそこそこ早いとは思います。とは言え、コンテキストスイッチ等は入るので1プロセスよりは遅いと思います。
しかし、そもそも128バイト程度のデータをどうやって500個のプロセスたちに渡すのでしょうか?その部分のオーバーヘッドも考える必要があると思います。

投稿日時 - 2005-03-07 23:51:36

お礼

非常に参考になりました。こんなに大量のプロセスを起こしたままにするプログラムってほとんどの人が経験ないですよね。「やってみないと分からない」と思います。
ご回答ありがとうございました。

投稿日時 - 2005-03-10 19:33:15

このQ&Aは役に立ちましたか?

2人が「このQ&Aが役に立った」と投票しています

回答(7)

ANo.6

No1 ency です。

[No2 nitscape さんへの「回答に対する補足」より]
> ここでお聞きしたかったのは、ひとつの短いデータを受け取り、
> それを500個の子プロセスからインターネット経由で端末に
> 送ることが可能かどうかと、このようなプログラムが妥当かどうか
> ということです。

可能かどうかは、サーバのリソース次第だとおもいますが、妥当かどうかは疑問です。
# このアプリしか立ち上げないサーバなのか、他のアプリとリソースを
# 共有するようなサーバなのか、ということも含めてですけど。

> TCPを使う理由は、端末がダイナミックIPの場合があり、端末側から
> keep-aliveして常に受信できるようにしたいと言う意図もあります。

クライアント側のホスト名がわかっているのであれば、サーバからのデータ送信のたびに毎回DNSで名前解決をすればIP Addressが都度変更されることにも対応できると思いますが、そういうことではないのでしょうか。
そうなれば、UDPでも全然問題ないように思うのですけど。
ま、500台の名前解決ともなれば、確かにそれだけで結構な時間を要してしまうでしょうけど。

とりあえず、私からの結論としては、次のとおりですかね。

(1) サーバのリソースに問題がないのであれば、hanako200 さんの提案も可能だと思います。
ただし、今後の拡張仕様等も考慮したうえでの設計が必要になってくるだろうと思います。

(2) サーバのリソースに問題があるような場合には、速度を犠牲にしることも考える必要があると思います。たとえば、上記の方法がその一例ですけど、もっと良い方法もあるかもしれません。

いずれにしろ、リソースと通信速度については、どこかで妥協点を見つけるしか方法はないと思います。

……こんなんじゃ、回答にはなっていませんかねぇ。。。

投稿日時 - 2005-03-07 13:35:06

ANo.5

追伸:
他の回答者の方が言う通り、インターネットを経由するという条件で既に到達時間の保障は不可能です。
時間の保障が絶対に必要なら、専用線を使うしかありません。

インターネットで、出来るだけ速くという事であれば、途中経路でのルーティング情報等が常にキャッシュされた状態にしてないと1発目は確実に遅くなってしまうので、例えば30秒とか1分に1回づつぐらい、小さなデータのやり取りを常に繰り返すようなロジックを入れたほうが良いかも知れません。
この辺りは経験則なので、実際に組んだ後で調整する必要があると思います。

投稿日時 - 2005-03-06 19:42:18

ANo.4

最近の UNIX なら1プロセスで1000個ぐらいソケットオープンできるようなので、500台程度なら1プロセスでやれば良いのでは?(ってむかし実際にやった事あるのは100本ぐらいなんだけど)
select() を使って接続制御と送受信制御のループをぐるぐる回せば出来ます。
送信の際は「できるだけ早く」という事なので、受信や新規接続要求は見ずにひたすら接続済みの全端末のソケットに書き込み続ければそこそこ早く送れるのでは?

それから、ここが肝心!
端末にデータを送るサーバ側では setsockopt() を使って TCP_NODELAY を必ず1に設定しておきます。これをやらないと、ソケット書き込みから実際の送信開始まで無意味に0.3秒程度待たされてしまいます。
TCPには、例えばtelnet等で細かすぎるデータが流れてネットワーク効率が下がるのを防ぐ目的である程度送信データが溜まるかタイムアウトになるのを待ってから送信するロジックが組み込まれています。
今回のように、規定長のデータをドカン!と送りたい場合は意味が無いので、上記設定でこの機能を外すのです。
あと、当然ながら送り元は一度に大量のデータを送るので回線速度による遅延を入れないよう、回線自体も100Mbpsなど太いものが必要です。

投稿日時 - 2005-03-06 19:34:48

補足

ご回答ありがとうございました。非常に参考になりました。さらにお尋ねしたいのですが、
・サーバでパッシブオープンしたソケットに端末からアクティブオープン(端末はいつネットに接続されるか分からないので)する場合、ご回答頂いた一つのプロセスで実現する方法はありますでしょうか?
・仮に、端末の台数だけプロセスをforkした場合、メモリ等のリソースはそこそこあるとして、一つ目のプロセスがデータを送出す時刻からから500個目のプロセスがデータを送出す時刻までの遅延はどんなものでしょうか?回線は十分太い(100Mbps)とします。

投稿日時 - 2005-03-07 14:25:26

ANo.3

インターネットを使った時点で、確実にとか、1秒以内とか考えるのは無理でしょうね。
できるだけという条件をつけるとか、1秒以内に反応がなければ失敗とみなして処理するなら可能でしょうが。

私はこの規模の通信を行うプログラムは経験無いのでよくわかりませんが、さすがに500プロセスというのは無駄に重いような気がします。
セッションも500もはりっぱなしでいいかどうか。内容によっては無駄に処理が重いだけかも。
具体的な内容が分からないので適切かどうかわかりませんが、私ならUDPにして1プロセスでやると思います。
タイムアウトとか受信の確認応答とか自前でプログラミングする必要がありますけど。
TCPだといろいろと面倒そうな気が・・。

投稿日時 - 2005-03-05 21:35:59

ANo.2

>500台の端末から1台のサーバにTCPセッションを張ったまま(forkして子プロセスにするなど)にして、
>このようなことを実現するのは可能でしょうか?
これは可能だと思いますが...


>データをできるだけ早く(1秒以内)インターネットの向こう側に点在している500台程度の端末に確実に
>送りたいのですが
これは無理だと思います。
確実に届ける(届けられたか届けられていないかをサーバーが知る)だけでしたら可能です。しかし1秒以内というのは。。。インターネットを介する限り到着時間は遅れることがあります。双方を光にするなど回線速度を速くしておけばある程度は防げますが、1秒以内という保障はできないと思います。

投稿日時 - 2005-03-04 20:37:34

補足

言葉たらずでしたので、補足させて頂きます。
「データをできるだけ早く(1秒以内)」の(1秒以内)を撤回させていただきます。(インターネット内での遅延は考慮しなくていいということです。)ここでお聞きしたかったのは、ひとつの短いデータを受け取り、それを500個の子プロセスからインターネット経由で端末に送ることが可能かどうかと、このようなプログラムが妥当かどうかということです。TCPを使う理由は、端末がダイナミックIPの場合があり、端末側からkeep-aliveして常に受信できるようにしたいと言う意図もあります。

投稿日時 - 2005-03-07 11:07:23

ANo.1

UDPじゃダメですか?

投稿日時 - 2005-03-04 20:23:02

あなたにオススメの質問