ネットワークプログラミング相談室 Port22

このエントリーをはてなブックマークに追加
952デフォルトの名無しさん:2008/12/28(日) 13:32:14
TIME_WAITで待つ時間を短縮とかそういう逃げしかないかと。。
953デフォルトの名無しさん:2008/12/28(日) 13:33:49
「自分のシステム内の」話か

なら、プロトコル変更するのがベストじゃね
954デフォルトの名無しさん:2008/12/28(日) 13:36:02
>今作っている少し複雑なプログラムで、記述子がどんどん大きくなっていって、いずれ
>ulimitで設定されて限界に達してしまいます。

問題がここなら、上限値を上げるしかない。
それでだめならシステムとして破たんしているということ。
955デフォルトの名無しさん:2008/12/28(日) 13:50:16
上限をあげるのはいいのですが、
プロセスが終了しないと、記述子がずっと上がり続けてしまうんです。
(なので、いつかは上限に達してしまう。)

以下のような簡単なプログラムのテストだと、プロセス内で何回socket, connect, closeしても、
closeした後すぐに前使った記述子が使えています。

while (1)
{
int sock = socket(...); // 毎回同じ記述子が使われる
...
connect(...);
...
close(sock);
}

956デフォルトの名無しさん:2008/12/28(日) 13:55:28
ちゃんとcloseしてないんじゃないの?
straceで調べてみたら
957デフォルトの名無しさん:2008/12/28(日) 14:04:50
shutdown してなくね?
958デフォルトの名無しさん:2008/12/28(日) 14:05:09
んー、してるんですがね。。
どっちが先にしろ、両方ともcloseしていれば、いいんですよね?
959デフォルトの名無しさん:2008/12/28(日) 14:07:21
closeしなければCLOSE_WAITになって今度はbindできなくなる。
960デフォルトの名無しさん:2008/12/28(日) 14:08:50
>毎回同じ記述子が使われる

それはたまたまそうなっただけw
961デフォルトの名無しさん:2008/12/28(日) 14:10:34
>>958
全部読んでからcloseするのと、
残してcloseするのでは全然違う。
というかSocket FAQを一度読んだ方がいい。

(システムの他の部分に影響が出る可能性があるので)
最後の手段だと思うが、
TIME_WAITの時間はほとんどのOSで変更可能。
962デフォルトの名無しさん:2008/12/28(日) 14:11:25
逆に、上の単純なプログラムで、なんでTIME_WAITが起きないかも謎です。
クライアントも同じ記述子番号がsocketで返ってくるし、サーバもacceptしたソケットが
毎回同じ記述子番号です。
963デフォルトの名無しさん:2008/12/28(日) 14:15:49
>プロセスが終了しないと、記述子がずっと上がり続けてしまうんです。

明らかにクローズしてない。ふつうは互いにFINを受け取るとディスクリプタは解放されるもん。
forkした後クローズしてないで終わってるところがあったりしてないか?
子プロセスはディスクリプタも引き継ぐが、クローズしないでプロセス終了してもソケットはつかんだまま昇天するから要注意だ。
964デフォルトの名無しさん:2008/12/28(日) 14:17:21
ディスクリプタが同じなのはたまたまだよ。
別のシステムで取り会いになるのが普通だから。
ディスクリプタが同じなのかどうかは問題ではない。
965デフォルトの名無しさん:2008/12/28(日) 14:31:31
closeはちゃんとしてると思います。コード的にも。
netstat -an|awk '/tcp/ {print $6}'|sort|uniq -c
なコマンドでstatusの数を見てますが、
netstatで見ても、TIME_WAITがどんどん増えていきます。(それ以外は変わらず)
なので、結果的にもちゃんとクローズされているのかと思っています。

定期的にsocket, connect, closeを繰り返すクライアントのプログラムを一旦、
Ctrl-Zで止めると、次第にTIME_WAITが減っていきます。(期待通り)
しかし、プロセスをfgで再開しても、socket(2)で開いていく記述子番号は止めたところから、
さらに増えていきます。
966デフォルトの名無しさん:2008/12/28(日) 15:09:43
forkした後クローズしてないで終わってるところがあったりしてないか?
子プロセスはディスクリプタも引き継ぐが、クローズしないでプロセス終了してもソケットはつかんだまま昇天するから要注意だ。
967デフォルトの名無しさん:2008/12/28(日) 15:15:37
forkはそもそもしていないです。サーバ側はマルチスレッドのサーバで、各スレッドは
同じソケットに対してacceptをしています。
968デフォルトの名無しさん:2008/12/28(日) 15:21:27
クローズはちゃんと出来てるんでしょ?漏れもそう思うよ。
だって中断したらTIME_WAITが減っていくわけだからね。

で、ディスクリプタの値がドンドン増えていくのと、同じ値が使われるのの違いが知りたいんでしょ?
単にそういうアルゴリズムなんじゃないの?
たとえば上のド単純なサンプルの場合、sendとかしてなくて、それが理由でソケットディスクリプタの数値が再利用されてるとかさ。

その辺は実装依存だろ。知ってる人がいるかも知れないけどね。
ソースが出てこない以上はそんな実装依存の部分の動作までわかんないよ。

ディスクリプタの値が増えようが増えまいが単にソケットの上限に達してるという結論は変わるまい。
上限を増やすか設計を見直すか、本当にforkが無いのかよっくチェックするかしか無いでしょ。

969デフォルトの名無しさん:2008/12/28(日) 15:26:30
単純なサンプルでも一応send,recvしてます。上のやつでは省略しただけでした。

ディスクリプタの値が増えようが増えまいが構わないですが、一方(増える方だけ)
上限に達します。なので、小さい番号が使えないので、大きい番号を選択してるという
挙動に見えます。
970デフォルトの名無しさん:2008/12/28(日) 15:34:30
じゃあ、ソケット上限に達したときに一時中断させてしばらくまってから再開したらどうよ。
それでも再開直後からソケット生成でコケるなら本当に誰かがつかみっぱなしなんじゃないの?
971デフォルトの名無しさん:2008/12/28(日) 15:43:39
上限手前で中断して、再開してもソケット生成に失敗しますね。
プロセスを一旦止めれば、また小さい番号の記述子から始まります。
closeはされているが、プロセスがsocketを解放しないということってありますか?
972デフォルトの名無しさん:2008/12/28(日) 15:45:24
so_reuseaddrセットしてみるとか
973デフォルトの名無しさん:2008/12/28(日) 15:55:31
三回は言わない。

>>961
> 全部読んでからcloseするのと、
> 残してcloseするのでは全然違う。

理解できてる?
shutdownとcloseの違いは理解している?

> というかSocket FAQを一度読んだ方がいい。

読んだ?
974デフォルトの名無しさん:2008/12/28(日) 15:56:24
>>971
ありますよ
975デフォルトの名無しさん:2008/12/28(日) 16:10:15
>> 全部読んでからcloseするのと、
>> 残してcloseするのでは全然違う。

>理解できてる?
>shutdownとcloseの違いは理解している?

理解しているつもりです。

>> というかSocket FAQを一度読んだ方がいい。

>読んだ?

読みました。書き込みが終了したらshutdown(s, 2) して、EOFを受信するのをまって、closeしています。

>974
どのような状況で起きますでしょうか?
976デフォルトの名無しさん:2008/12/28(日) 17:25:19
恐慌は人の心によって引き起こされる
977デフォルトの名無しさん:2008/12/28(日) 17:39:33
問題解決しました。
使っていたライブラリ(libevent)の使い方が間違っていたのが原因でした。
リクエストの度に毎回event_init()をしていました。。。
その後、ファイルディスクリプタをaddしていて、libevent内部でそのディスクリプタを
つかみっぱなしのままという感じでしょうか。
なので、コネクションはcloseされていても、ファイルディスクリプタが解放されないという
変な現象が起きていました。

色々相談に乗って頂いた方、ありがとうございました。
結果的に私のしょぼすぎるミスでしたが、とても勉強になりました。
978デフォルトの名無しさん:2008/12/28(日) 17:48:51
よかったよかった
979デフォルトの名無しさん:2008/12/28(日) 18:01:19
ここはおまいの日記です
980デフォルトの名無しさん:2008/12/28(日) 18:48:08
絶対自分のミスを疑わない香具師っているよな
981デフォルトの名無しさん:2008/12/28(日) 18:49:57
かれこれ70レス消費したのか
982デフォルトの名無しさん:2008/12/28(日) 18:50:35
919の人気に嫉妬
983デフォルトの名無しさん:2008/12/28(日) 19:03:55
それじゃクローズされてないし…
close==ファイルディスクリプタの解放だからPOSIXでは。
984デフォルトの名無しさん:2008/12/28(日) 19:08:32
livevent使ってたんかいw
先にそれを家w
まぁ

よかったぉ
985デフォルトの名無しさん:2008/12/28(日) 19:29:26
クローズしてたと思ったけど、
ファイルディスクリプタ管理に失敗していたわけですね。
close(2)の帰り値はチェックしてないと。
986デフォルトの名無しさん:2008/12/28(日) 19:44:01
liveventって何?
987デフォルトの名無しさん:2008/12/28(日) 20:00:25
俺はこういう流れ好きだぜ?
あーだこーだ言ったりして色々勉強になるし
パズルみたいで。
最初はすごい不思議な話なのが、最後にすっきり解決って楽しい。
バグって面白くね?(他人のを見ているぶんには)
988デフォルトの名無しさん:2008/12/28(日) 20:07:38
>>977 のファイルディスクリプタをつかみっ放しって
意味わからない。dupしてるとか?
989デフォルトの名無しさん:2008/12/28(日) 20:12:35
だからstraceしれって言ったのに
990デフォルトの名無しさん:2008/12/28(日) 20:14:00
>>988
いや、クローズに失敗していただけ。
event_initして管理テーブル飛ばしてたから。
991デフォルトの名無しさん:2008/12/28(日) 20:16:20
straceもいいけど、エラーチェックぐらいしようよ
992デフォルトの名無しさん:2008/12/28(日) 21:02:52
きみらなんでそんなにひまなの?
しぬの?
993デフォルトの名無しさん:2008/12/28(日) 21:08:18
994デフォルトの名無しさん:2008/12/28(日) 21:15:54
gj
995デフォルトの名無しさん:2008/12/28(日) 21:24:10
乙py
996デフォルトの名無しさん:2008/12/28(日) 21:50:04
うめ
997デフォルトの名無しさん:2008/12/28(日) 21:51:40
来年はスーパーインフレ
998デフォルトの名無しさん:2008/12/28(日) 21:52:22
999デフォルトの名無しさん:2008/12/28(日) 21:52:54
1000デフォルトの名無しさん:2008/12/28(日) 21:53:31
10011001
このスレッドは1000を超えました。
もう書けないので、新しいスレッドを立ててくださいです。。。