• ベストアンサー

ソケットを使った通信

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

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

  • ベストアンサー
回答No.7

No.4,5 の MiracleCat 再びです。 >・サーバでパッシブオープンしたソケットに端末からアクティブオープン(端末はいつネットに >接続されるか分からないので)する場合、ご回答頂いた一つのプロセスで実現する方法はありま >すでしょうか? この辺りは socket の基本ですが、bind() でポート番号を固定したソケットを listen() 状態にして、select() に対して READ で待ちうけすると、端末が接続して来た時に select() から制御が戻るのですかさず accept() して、出てきたソケットを片っ端から READ で select() にぶら下げます。 端末からデータが来たり切断されたら select() が抜けてくるので処理してあげます。 問題の128バイト程度のデータがどこから来るか知りませんが、それもソケット経由で来るのならこの1つの select() の下にぶら下げて待ち合わせして、データが届いたらその時点でオープンしている全ソケットに非同期で片っ端から書き込むループを回すというような感じです。 非同期書き込みするのは、万が一にも制御ループをブロックさせないためです。 >・仮に、端末の台数だけプロセスをforkした場合、メモリ等のリソースはそこそこあるとして、 >一つ目のプロセスがデータを送出す時刻からから500個目のプロセスがデータを送出す時刻 >までの遅延はどんなものでしょうか?回線は十分太い(100Mbps)とします。 すみません、それだけ大量のプロセスを上げての処理ってやった事が無いので何とも言えませんが、プロセススイッチが比較的高速なUNIXの場合、全プロセスがスワップ落ちせずオンメモリでいればそこそこ早いとは思います。とは言え、コンテキストスイッチ等は入るので1プロセスよりは遅いと思います。 しかし、そもそも128バイト程度のデータをどうやって500個のプロセスたちに渡すのでしょうか?その部分のオーバーヘッドも考える必要があると思います。

hanako200
質問者

お礼

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

その他の回答 (6)

  • ency
  • ベストアンサー率39% (93/238)
回答No.6

No1 ency です。 [No2 nitscape さんへの「回答に対する補足」より] > ここでお聞きしたかったのは、ひとつの短いデータを受け取り、 > それを500個の子プロセスからインターネット経由で端末に > 送ることが可能かどうかと、このようなプログラムが妥当かどうか > ということです。 可能かどうかは、サーバのリソース次第だとおもいますが、妥当かどうかは疑問です。 # このアプリしか立ち上げないサーバなのか、他のアプリとリソースを # 共有するようなサーバなのか、ということも含めてですけど。 > TCPを使う理由は、端末がダイナミックIPの場合があり、端末側から > keep-aliveして常に受信できるようにしたいと言う意図もあります。 クライアント側のホスト名がわかっているのであれば、サーバからのデータ送信のたびに毎回DNSで名前解決をすればIP Addressが都度変更されることにも対応できると思いますが、そういうことではないのでしょうか。 そうなれば、UDPでも全然問題ないように思うのですけど。 ま、500台の名前解決ともなれば、確かにそれだけで結構な時間を要してしまうでしょうけど。 とりあえず、私からの結論としては、次のとおりですかね。 (1) サーバのリソースに問題がないのであれば、hanako200 さんの提案も可能だと思います。 ただし、今後の拡張仕様等も考慮したうえでの設計が必要になってくるだろうと思います。 (2) サーバのリソースに問題があるような場合には、速度を犠牲にしることも考える必要があると思います。たとえば、上記の方法がその一例ですけど、もっと良い方法もあるかもしれません。 いずれにしろ、リソースと通信速度については、どこかで妥協点を見つけるしか方法はないと思います。 ……こんなんじゃ、回答にはなっていませんかねぇ。。。

回答No.5

追伸: 他の回答者の方が言う通り、インターネットを経由するという条件で既に到達時間の保障は不可能です。 時間の保障が絶対に必要なら、専用線を使うしかありません。 インターネットで、出来るだけ速くという事であれば、途中経路でのルーティング情報等が常にキャッシュされた状態にしてないと1発目は確実に遅くなってしまうので、例えば30秒とか1分に1回づつぐらい、小さなデータのやり取りを常に繰り返すようなロジックを入れたほうが良いかも知れません。 この辺りは経験則なので、実際に組んだ後で調整する必要があると思います。

回答No.4

最近の UNIX なら1プロセスで1000個ぐらいソケットオープンできるようなので、500台程度なら1プロセスでやれば良いのでは?(ってむかし実際にやった事あるのは100本ぐらいなんだけど) select() を使って接続制御と送受信制御のループをぐるぐる回せば出来ます。 送信の際は「できるだけ早く」という事なので、受信や新規接続要求は見ずにひたすら接続済みの全端末のソケットに書き込み続ければそこそこ早く送れるのでは? それから、ここが肝心! 端末にデータを送るサーバ側では setsockopt() を使って TCP_NODELAY を必ず1に設定しておきます。これをやらないと、ソケット書き込みから実際の送信開始まで無意味に0.3秒程度待たされてしまいます。 TCPには、例えばtelnet等で細かすぎるデータが流れてネットワーク効率が下がるのを防ぐ目的である程度送信データが溜まるかタイムアウトになるのを待ってから送信するロジックが組み込まれています。 今回のように、規定長のデータをドカン!と送りたい場合は意味が無いので、上記設定でこの機能を外すのです。 あと、当然ながら送り元は一度に大量のデータを送るので回線速度による遅延を入れないよう、回線自体も100Mbpsなど太いものが必要です。

hanako200
質問者

補足

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

  • terra5
  • ベストアンサー率34% (574/1662)
回答No.3

インターネットを使った時点で、確実にとか、1秒以内とか考えるのは無理でしょうね。 できるだけという条件をつけるとか、1秒以内に反応がなければ失敗とみなして処理するなら可能でしょうが。 私はこの規模の通信を行うプログラムは経験無いのでよくわかりませんが、さすがに500プロセスというのは無駄に重いような気がします。 セッションも500もはりっぱなしでいいかどうか。内容によっては無駄に処理が重いだけかも。 具体的な内容が分からないので適切かどうかわかりませんが、私ならUDPにして1プロセスでやると思います。 タイムアウトとか受信の確認応答とか自前でプログラミングする必要がありますけど。 TCPだといろいろと面倒そうな気が・・。

  • nitscape
  • ベストアンサー率30% (275/909)
回答No.2

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

hanako200
質問者

補足

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

  • ency
  • ベストアンサー率39% (93/238)
回答No.1

UDPじゃダメですか?

関連するQ&A

  • ソケット通信で同時受信の制限?

    こんにちは。 早速ですが、ソケット通信について質問です。 複数クライアント(Win)からサーバ(UNIX)に対して、connect()し、サーバ側はaccept()したら、それぞれに対しfork()で子プロセスを作っています。 そこで、50台くらいのクライアントから一気にconnect()すると通信エラーとなってしまうのですが、なにか制限があるのでしょうか? connect()のタイミングをずらせば、それぞれのクライアントとサーバの子プロセスでやり取りができます。 一斉にconnect()される場合の通信エラーの原因や対処法などをご教授願います。 初歩的なことかもしれませんが・・・。 よろしくお願いいたします。

  • ソケット通信

    現在プロセス間通信について学んでおり、 今はソケットを使ったプロセス間通信のプログラムを書いています。 そのソケット通信での質問なのですが、 2台のパソコンでINETドメインのソケットを使って プログラムを書いているのですが、 サーバーを実行した後、 別のパソコンでサーバー側のパソコンのIPアドレスを指定して クライアントを実行しようとすると、 connect:Connection timedout と表示されて実行できません。 同じプログラムをUNIXドメインで 1台のパソコンで実行すると正しく実行できます。 これは、プログラムに問題があるのでしょうか? それとも、ソケット通信を行う際には 何かパソコン等の設定が必要なのでしょうか? 教えてください。お願いします。 あと、セマフォを用いたプロセス間通信のサンプルプログラムが のっているホームページなどご存知でしたら、 教えていただけるとありがたいです。

  • ルーターを介したTCPとUDP通信の違いについて

    端末1---(LAN側)ルーター(WAN側)---端末2 というふうに接続されていた場合を想定します。 上図で端末1がTCPセッションを端末2と張ろうとした場合(httpなど)のルーターの動きについて確認させてください。 <ルーターの動き> (1)端末1からのTCPセッション開始のパケットを受信す るとMACアドレスとIPアドレスをルーターのものにす り替え、ポート番号も変えて端末2に渡す。この時の アドレスとポート番号の対応表を記憶しておく。 (2)端末2から応答が返ってきた場合(1)で記憶した対応表 を基にパケットのMAC,IP,ポートをすり替えて端末1 に渡す。 (3)TCPのセッションが終了したら(1)で記憶した対応表は 破棄する。 とりあえずこの解釈は正しいでしょうか? なお、UDP通信の場合は(1)の対応表を全く作らないということで良いでしょうか? ご教授よろしくお願いします。

  • デーモンとしてサーバプログラム(ソケット使用)を稼動させるには?

    質問はタイトルの通りなのですが、いま私は、ソケットを用いてサーバプログラムを作成しております。私の作ろうと思っているプログラムは、forkを用いて、親プロセスにクライアントからの接続を待たせ、接続があったら、子プロセスに処理を行わせ、親プロセスは接続待ち(accept)に戻ります。あとは、この処理をひたすらループさせるだけです。  ですが、どのタイミングでforkやら無限ループを入れればよいのか分かりかねます。  ネットで色々調べていたら以下のサイトを発見し、それっぽいプログラムのサンプルが載っていたのですが、雰囲気的には、こんな感じでよろしいのでしょうか? http://kansai.anesth.or.jp/gijutu/perl/man-socket.php#tcp-msrv です。  どなたかご教授して頂けると幸いです。よろしくお願いします。

    • ベストアンサー
    • Perl
  • TCP/IP通信3ハンドシェイクについて

    TCP/IPのTCP通信の3ハンドシェイク通信に関して質問なのですが、インターネットを使ったある端末でセンターのサーバーと6秒に1度程度3ハンドシェイク通信を行ってインターネット回線が正常かどうかを判定する機能を持っているそうなのですが、その時に1回の通信でどの程度のパケットをやり取りしているのかということを質問してみたら、約1.2kbyte程度のパケットをやり取りしていると業者の方が言っていました。 ちょっと興味があってWireSharkでこの端末とサーバ間のパケット通信をのぞいてみたところ、端末が1.2kbyte送信していたのですが、サーバからのACKと思われるパケットが1.2kbyteのパケットを返してきていて、再度端末が60バイト程度のパケットをサーバのIPアドレスに送信していました。 私はてっきり、端末とサーバー間のこの3ウェイハンドシェイクのパケットの総量が1.2kbyteだと思っていたのですが、これだと1.2k + 1.2k + 60 = 2.46kbyteとなると思うのですが、パケットのやり取りとしては正しいのでしょうか? サーバー側が受信したら同じ容量の1.2kbyteのデータをACKとして返してきているように思うのですが、Wiresharkで見ても全く同じデータでは無いようでした。サーバはデータを受け取ったら、ちゃんと受信したという1 or 0のデータみたいなものを返せばよいだけだと思うのですが、理由はあるのでしょうか?

  • 衛星通信ワイドスターの遅延時間について

     アイデア段階ですので実際可能か調べていないのですが、ワイドスターの端末2台を使用してpeer to peer の通信(TCP/IP のソケット通信のようなもの)させられないかと考えています。   そこでこのような事を実際に試された方がおられませんでしょうか? もしもおられましたた 1 どの程度の通信速度が出たでしょうか? 2 通信の遅延時間(例としてpingを打って帰ってくる時間のようなもの) 3 その他あらかじめ想定しておくべき問題点 など教えてください。

  • TCPセッション状態「CLOSE_WAIT」につい

    TCPセッション状態「CLOSE_WAIT」について質問です。 ■事象 WEBサーバを運営していて、 画像ファイルのアクセスが10リクエスト/1秒 程度あるのですが、 Apacheの「http://localhost/server-status?refresh=1」で状況を確認すると、 "W" Sending Replyがどんどん増加していき、 準備していた1024スレッドを全て使い果たしてしてサーバダウンとなる事象が発生しています。 サーバダウン時に「netstat -an」でTCPセッションを確認したのですが、 「CLOSE_WAIT」が大量に(950程度)残っていました。 TCP通信が完全に終了していないく、 不完全なTCP通信がプロセスを圧迫して、新しいリクエストを受け付けられない、 という状況です。 ちなみに、 画像ファイルのアクセスは他サイトからの直リンクになります。 他サイトに<img src="http://質問者のサイト.com/image.jpg">という直リンクがあり、 他サイトのPVが10アクセス/1秒あるということです。 ■環境 OS : Windows 7 64bit WEB : Apache/2.2.27 (Win64) PHP/5.4.26 ■質問 なぜ「CLOSE_WAIT」が大量に残ってしまうのか、理由を教えて下さい。 また、具体的な解決方法(オペレーション付きが望ましいです)を教えて下さい。 ■備考 ネットワーク機器が影響かと思い、別の製品にしたのですが、 解決せずでした。 サーバのKeepAlive系の設定かな?と思っています。

  • forwarderオンリーのDNSサーバのキャッシュをやめたい

    win2Kserver上のDNSサーバ(MS純正のやつ)のforwarderのキャッシュをやめる方法を教えていただきたいのです。 現在、会社の業務システムLAN上で、win2K serverを使ってDNSサーバを立ち上げているます。今回、わけあって新たに別のUNIXマシンでDNSサーバを立ち上げ、社内のほとんどの端末(win95,win2Kpro)はそのUNIXマシンで動いているbindをDNSサーバとして利用することにさせました(これらの端末にはDHCPでDNSサーバを渡しているため簡単に変更できます)。ただ、社内の300台程度の端末はDNSサーバを固定で持っているために、今後も昔のDNSサーバであるwin2KservのマシンをDNSとして稼動させつづけなくてはなりません。そこで、win2Kservでfowarderだけを稼動させることにしたのですが、そいつが端末からの問い合わせ結果をcacheしてしまい困っています。出来れば、まったくcacheさせたくないのですが、その方法をご存知の方はいらっしゃいますか?MMCのDNSスナップインの画面ではそれらしい画面はありませんでした。レジストリをいじれば可能じゃないかと予想してるんですが、それらしい文書を見つけることが出来てません。どなたかご存知の方いらっしゃいましたら教えてください。なお、このwin2kservマシンにtcp-relayなどの、MS純正以外のソフトをインストールすることは出来ません。

  • プロキシサーバーとの通信を補助する装置

    今まではルータ1台で事務所内のすべてのPCのDHCP、ネット通信を行わせるシンプルなネットワークだったのですが、情報漏洩の防止などを目的にプロキシサーバーを導入する予定なのですが、現在ネットワーク内にあるセンサー通報のためのTCP/IP機器などが常にサーバーに対して通信していたりしているのですが、その端末にはプロキシサーバーとの通信機能がないのです。もし、ネットワーク内でプロキシサーバーを導入した場合、このような端末もプロキシサーバーと通信してインターネット接続できるようにしてくれるような方法や装置などはありますか?

  • アイディアを下さい。

    画像通り、実現させたいのですが方法が分りません。 分らないと言ってもどの様に実施するか、分らないのです。 (1)CL(クライアント)からServerに受信させる方法は、TCPサーバーを  利用した方が良いのか、また別の方法が…。(TCPは苦手) (2)次に受信後起動させるのはProcessクラスのStartメソッドを使って起動し、  プロセスチェック後、(1)通りに逆送信もしくはメールサーバでメールする そこでアイディアを下さい。使用するのは.net 4.5でVB.NETです。 APIやDLLもあれば教えて下さい。