- PR -

Socketの監視

1
投稿者投稿内容
maru
ぬし
会議室デビュー日: 2003/01/27
投稿数: 412
投稿日時: 2003-06-26 11:33
いつもお世話になってます。
現在、Socke通信のクライアントアプリケーションを作っています。

サーバ側でクローズされたり、物理的にネットワークが切断されたりした場合に、
をれを検出し、イベントを発生させるため、接続後にソケット監視スレッドを作り、
run()の中で、ソケットのisClosed()を監視しているのですが、検出されません。

connect()やsetSoTimeout()にタイムアウト時間を設定してもダメでした。

サーバ側でクローズされたり、物理的に切断されてもisClosed()は変化しないのでしょうか?
こういった場合どのようにすればいいのでしょうか?

ご存知のかたおられませんか?


H2
ぬし
会議室デビュー日: 2001/09/06
投稿数: 586
お住まい・勤務地: 港
投稿日時: 2003-06-26 13:30
1.4以上であれば、isInputShutdown()が使えるかもしれません。ただ物理的に切れてしまった場合はわかりません。試してみてください。
raccoon
ベテラン
会議室デビュー日: 2002/12/18
投稿数: 58
投稿日時: 2003-06-26 14:58
これはよくあるkeepalive問題でしょうかね。

getKeepalive()がtrueであることを確認して(falseだったら
setKeepalive(true)しておく)試してみましょう。
検出されるはずです。ただし約2時間かかります(笑)。

TCPには,「一定時間無通信なら,双方にパケットを送信し,
つながってなければ切断する」というkeepaliveの仕組みが
ありますが,この間隔はOSにより異なりますが,たいてい
2時間なので,TCPプログラミングではよく問題になります。
これはTCPの仕様なので,Javaに限らず他の言語でも同じです。

一部のOS(Win2000とか)では,keepaliveの時間を変更する
ことができるらしいです(やり方は知りませんが)。

「どうしても」というなら,一定時間ごとに自分でなんらかの
無効データを送信し,相手がそれに応答するという仕組みを
自力で作り込むなどの工夫が必要でしょうか。

# H2さんのおっしゃったisInputShutdown()が使えるなら
# それに越したことはないですが。
# でも少なくとも物理切断までは検知できないような気がするなぁ。
maru
ぬし
会議室デビュー日: 2003/01/27
投稿数: 412
投稿日時: 2003-06-26 15:43
こんにちは。ありがとうございます。

インターネットでも同様の記事を見つけました。
http://www.kt.rim.or.jp/~ksk/sock-faq/unix-socket-faq-ja-2.html

KeeyAliveは実用的ではないのでNGですね。
実は相手方のサーバというのは FTPサーバです。
FTPには何もしないコマンド「noop」というのがあったので、定期的に送ってみたのですが、
監視用スレッドの「noop」と通常のデータ送受信とがごっちゃになって、synchronized で
同期処理にしてみたのですが、あまりスムーズな処理にはなりませんでした。
つくりが悪いといわれてしまえばそれまでですが・・・。

物理的な切断の検出はおいといて、サーバ側で正常に切断された事すら検出できません。
接続中にサーバを停止してもisClosed()もisConnected()もisInputShutdown()
もisOutputShutdown()も変化してくれません。

ただ単にサーバからの正常な切断をクライアントで検出したいだけなんですけど・・・。
昔、VBでwinsock.ocxでやったときは簡単にできたような気がしたんだけど。
maru
ぬし
会議室デビュー日: 2003/01/27
投稿数: 412
投稿日時: 2003-06-26 16:06
Win2000についてるFTPサーバの管理ツールに、現在接続されているユーザと
その時間が表示されるところがありました。タイムアウトの設定を10秒にし
ているのに、なぜか接続から2分くらいたってから自動切断されます。

自動切断されても、isClosed()など、変化してくれません。
手動で切断しても同様です。

フリーのFTPクライアントなどは、きちんと切断を検出して画面にメッセージ
を出しているのに・・・。

maru
ぬし
会議室デビュー日: 2003/01/27
投稿数: 412
投稿日時: 2003-06-27 09:38
こんにちは。

そもそも、サーバ側でクローズしてもクライアント側のSocketは勝手にクローズされない
のかな?

正しいやり方かどうかはわかりませんが、接続監視スレッドでisClosed()等をみないで、
緊急データの送信を行うメソッド sendUrgentData というものがあったので、それを使って
定期的に緊急データを送る方法でやってみました。

サーバ側で切断されたり、物理的に切断された(手元のケーブル抜いただけだが)場合でも、
IOExceptionが発生し、切断を検出する事ができました。
その後、クライアント側のソケットをクローズするようにしました。
nil
会議室デビュー日: 2003/06/17
投稿数: 14
投稿日時: 2003-06-29 20:38
相手がcloseすると、Socket#getInputStreamで得たInputStreamが終端に達するのでは。

もしnioを使っているなら、SocketChannel#readが-1を返す事で検出できます。
maru
ぬし
会議室デビュー日: 2003/01/27
投稿数: 412
投稿日時: 2003-07-03 10:54
こんにちは。

sendUrgentDataで定期的にデータ送信する方法ですが、当初はうまくいっていたの
ですが、FTPサーバによってはこのようなデータを受け付けた場合に固まる(次の
データ待ちになる?)ものもあるようでNGでした。

やはり、InputStreamのreadで監視するべきなんでしょうか?
データ送受信のスレッドとソケット監視のスレッドを分けたいのですが・・・。
一度、InputStreamのreadで監視するように作り変えてみます。

1

スキルアップ/キャリアアップ(JOB@IT)