• ベストアンサー

ソケット通信で、250本しか接続できない

solaris上で、ソケット通信をするプログラムを作成しております。 サーバー側にクライアントを多数接続したいのですが、 250本くらい接続するとサーバー側でacceptを呼び出したタイミングで セグメント例外を出力して異常終了してしまいます。 ここからは推測なのですが、 サーバー側のディスクリプタが255までは正常に動作するため、 ディスクリプタの数が256に制限されているのではないかと思います。 そこで、ulimitでdescriptorsを増やしたり、 setrlimit関数で、RLIMIT_NOFILE値を増やしたりしてみましたが、 状況は全く変わりませんでした。 念のためスタックサイズを増やしてもみましたがやはり効果ありませんでした。 どなたか、解決方法をご存じでしたら、ご教授頂けませんか? よろしくお願いします。

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

  • ベストアンサー
  • tatsu99
  • ベストアンサー率52% (391/751)
回答No.6

fort-cは現在sun studioに統合されたようです。 無償で評価版はダウンロードできますので、 gccで解決出来ないときは、こちらを試されては如何でしょうか。 参考URLからダウンロードできます。

参考URL:
http://jp.sun.com/products/software/tools/studio/
uu0v0uu
質問者

お礼

いろいろありがとうございました。 スレッドが古くなってしまったので閉じさせて頂きます。 あとは自分でなんとかやってみようと思います。

その他の回答 (5)

  • g_vikke
  • ベストアンサー率16% (15/90)
回答No.5

FDより、プロセス数とかスレッド数とか関係してそうですね。acceptして、作るんでしょ? どこで死んでるかだけですけどね。

uu0v0uu
質問者

お礼

せっかく回答頂いたのですが、 シングルスレッドで作成していて、 acceptしてもプロセスもスレッドも増加しておりませんので、 その辺は大丈夫かと思います。

  • tatsu99
  • ベストアンサー率52% (391/751)
回答No.4

>となると環境の違いか、もしくは別の値の制限を受けてしまっているのでしょうか。 >差し支えなければ、tatsu99さんの試した環境を教えて頂けますでしょうか? solaris8(sparc)でfort-cでコンパイルしました。 gccは使用していません。 私が確認したときは、getrlimitで取得した結果が、ソフトリミット=256、ハードリミット=1024でした。 ソフトリミット=300にして、約300迄の接続を確認しました。使用されているOSはインテル版でしょうか? 当方はSPARC版で64ビットモードでコンパイルしています。 うーむ。環境の違いか、別の値の制約・・・ 問題は、それが何なのかですね。・・・役に立てなくて申し訳ない。

uu0v0uu
質問者

お礼

ありがとうございます。 こちらもSPARC版ですが32ビットモードです。 コンパイラも違うみたいですし、そのあたりが怪しいですね。 なんとかしてその辺も変えてやってみようと思います。

  • tatsu99
  • ベストアンサー率52% (391/751)
回答No.3

>setrlimit関数で、RLIMIT_NOFILE値を増やしたりしてみましたが 当方で確認しましたところ、setrlimit関数でソフトリミットを増やしたところ、256を越える接続に成功しました。 従って、アプローチとしては、この方法で良いかと思います。 getrlimitで、現在のリソースを取得し、そのソフトリミットを、setrlimitで更新しました。 ソフトリミットを増加させる前は、acceptのエラーは、errno=24(EMFILE:Too many open files )が返ります。 セグメンテーションエラーは、発生しません。 まず、#1のかたが言われているように、セグメント例外を出力して異常終了するのを修正するのが、先かと思い ます。それが、解決すれば、同時オープンソケット数の拡張は、可能かと思います。 acceptでセグメンテーションエラーが起こるとすると、 第3パラメータのaddrlen(第2パラメータのサイズ)が、正しくない可能性があります。これは、IN/OUTのパラメータなので、毎回、正しく設定し直してから、呼び出す必要があります。その点は、確認されましたでしょうか。 話題は、変わりますが、1プロセスで256以上のソケットを作成し、接続する必要があるのでしょうか? もし、256以上の接続ができても、パフォーマンスの観点から、実用に耐えるかどうかが疑問です。この点は問題ないのでしょうか。

uu0v0uu
質問者

お礼

ありがとうございます。 方向はあっているとのことなので、もう少し頑張ってみます。 下の欄にも書きましたが、セグメント例外に関してはミスでした。 acceptはおっしゃるように Too many open files のエラーが返るようです。 > getrlimitで、現在のリソースを取得し、そのソフトリミットを、setrlimitで更新しました。 同様にしてやってみました。 getrlimitで変更後の値も確認しましたが、それでもToo many open files のエラーが発生します。 逆にソフトリミットの値を減少させると、接続できる数が減るため、値の変更はできているようです。 となると環境の違いか、もしくは別の値の制限を受けてしまっているのでしょうか。 こちらの環境は、solaris8でコンパイラはgccの2.95.3です。 差し支えなければ、tatsu99さんの試した環境を教えて頂けますでしょうか? パフォーマンスまで心配して頂いてありがとうございます。 もちろん動かしてみないとはっきりしたことはわからないのですが、一応動作するように作っているつもりです。

  • ponshige
  • ベストアンサー率40% (12/30)
回答No.2

/etc/systemファイルで次のパラメータを設定することでシステムでの制限を変更することができます。 rlim_fd_max ハードリミット rlim_fd_cur ソフトリミット 設定例) set rlim_fd_max=0x10000 ただし、この拡張はあくまで64ビット環境だけですので、同じシステムを32ビット環境にしたり64ビット環境にするような場合は/etc/systemファイルでの設定は危険です。 またselect()を使用するユーザアプリケーションをコンパイルする際にFD_SETSIZEマクロを定義することでselect()が扱うことのできる記述子の再設定が可能になっています。 sun% cc -DFD_SETSIZE=4096 .... ・fopen(3C)で開くことのできるファイル数 とありましたが、これではダメですかね? 実際に自分でやったわけではなく申し訳ないですが。。 手元のUNIXネットワークプログラミングの本では <sys/types.h>ヘッダ(<sys/select.h>かも?)の #define FD_SETSIZE 256 となっているものを変更したあと、カーネルの再コンパイルが 必要なようです。

参考URL:
http://www.nsug.or.jp/readme/no30/FA30.html
uu0v0uu
質問者

お礼

ありがとうございます。 /etc/systemはいじってみましたが、だめでした。 rlim_fd_max ハードリミット rlim_fd_cur ソフトリミット これらの値を設定し、リブートしてみました。 確かにlimitで確認できる数値に変化はあるのですが、 なぜか動作させた時に256で制限を受ける状況は変わりませんでした。 FD_SETSIZEもデフォルト1024でした。 念のため、-DFD_SETSIZE=1024と明示的に指定してみましたがそれでもうまくいきませんでした。 なかなかうまくいかないものですが、自分でもいろいろ試してみます。 URLありがとうございました、とても参考になりました。

  • coredump
  • ベストアンサー率46% (12/26)
回答No.1

solarisは使った事無いのですが、一般的に OSの制限にひっかかってセグメント例外を出すって のは考えにくいです。 プログラム上のミスが原因である可能性が高いと 思います。 僕だったら、デバッガでacceptの引数のポインタが 正常な値かのチェックとか、最小限のコードを書いて テストしますね。

uu0v0uu
質問者

お礼

ありがとうございます。 セグメント例外はミスでした。 ディスクリプタが足りなくなって、acceptがエラーで返ってきたのをファイルに吐こうとして、 ファイルをオープンする部分でやっぱりディスクリプタが足りないので、 ファイルがオープンできなかった、というエラーをさらにファイルに・・・・ というループにハマってました。