- - PR -
socketのタイムアウトについて
| 投稿者 | 投稿内容 | ||||
|---|---|---|---|---|---|
|
投稿日時: 2004-01-28 14:14
事情によりJDK1.1.1を使ってTCP/IPのプログラムを
作っています。 socket(remoteAddr,remotePort) とした場合、接続相手がいない場合などに接続のタイムアウトまでに 時間がかかってしまいます。 JDK1.4ではconnet()に時間指定が出来るメソッドが追加になっていますが、 JDK1.1.1でこの状況を回避する方法を検討しています。 今検討しているのは以下の通りです。 1.DatagramPakcetを使ってポート7に対してECHO要求を発行する。 2.JNIを利用してPingを発行し、接続相手が正常であることを確認して socket()を実行する。 1.の場合、相手がECHO要求を無視するような設定の場合、無効になり、 2.の場合、nativeのPingのコードをC/C++で作成するのは避けたいと思っています。 その他よい回避策あれば、ご教授お願いします。 | ||||
|
投稿日時: 2004-01-29 23:20
fujiikiさん、こんにちは。
socketを実行するスレッドを独立させ、 タイムアウトをシミュレーションしてはいかがでしょうか? 状態遷移モデルと排他制御を組み合わせれば できるような気がします。 | ||||
|
投稿日時: 2004-01-30 02:59
connect に割り込むのは無理な気がします。 | ||||
|
投稿日時: 2004-01-30 09:43
Kissingerさん、Keisukeさん
回答ありがとうございます。 Kissingerさんがおっしゃっている内容のことを http://www.javaworld.com/jw-09-1999/jw-09-timeout.html を参考に行ってみました。 タイムアウトは親スレッド側で検出できるのですが、 実際にsocketを実行している子スレッドがリターンしてこないので 全体の実行時間自体の制御は出来ませんでした。 Keisukeさんが言われている通りです。 この方法はあきらめて、外部コマンドのpingをコールして 接続相手の状態を確認することにしました。 (これでも実行時間に問題があれば、 JNIでpingを実装するしかないと思っています。) 以上です。 | ||||
|
投稿日時: 2004-01-30 10:52
もしかしたらできるかも、という仮説です。実際に試していないですが。
JDK1.3のAPIコードを読んでの考えなので、JDK1.1で適用できるかどうかも分かりません --; Sun JDKのjava.net.PlainSocketImpl(java.net.SocketImplのデフォルト実装)の nativeメソッドに、socketConnect(),socketBind(),socketSetOption()などのメ ソッドがあります。どうも、バークレーソケットインターフェイスの単純なラッパに なっているようです。 jdk1.3以前のjava.net.Socketはpublicコンストラクタ内部でPlainSocketImplを 生成して即PlainSocketImpl#bind()&connect()をコールしてしまっていますが、 ここを避けるコードを書くと、何とかならないでしょうか? (例) Socket#setSocketImplFactory()で、カスタムSocketImplFactoryを登録。 カスタムSocketImplFactoryが生成するSocketImplの実装は以下の通り。 ・connect()、bind()では、実際のconnect処理、bind処理を行わない。 初回の送受信時に初めて実行するよう、処理を遅延させる戦略とする。 ・socketSetOption()を直接たたけるインターフェイスを作成する。 これを利用して、SO_TIMEOUTオプションの値設定を実際のconnect 処理より前に行えるようにする。 ・実際のconnect、bind、setSockOpt等の処理は、PlainSocketImplのnative メソッドに委譲する。(privateなので、リフレクションで無理やりコール) これにより、JNIを使用することなく、connectを行う前にSO_TIMEOUTオプション をsetSockOptできるようになると思います。それがconnectに対して効くのかどう かは、JVMの実装依存になってしまいますが・・・ [ メッセージ編集済み 編集者: シュン 編集日時 2004-01-30 10:55 ] [ メッセージ編集済み 編集者: シュン 編集日時 2004-01-30 11:08 ] | ||||
|
投稿日時: 2004-01-30 14:04
シュンさん ありがとうございます。
JDK1.4で以下の順で実行してみました。(JDK1.1にはconnect()が無いので) InetSocketAddress endpoint= new InetSocketAddress(InetAddress.getByName(server),servPort); Socket socket=new Socket(); socket.setSoTimeout(100); socket.connect(endpoint); 結果はsetSoTimeoutで設定した時間ではタイムアウトになりません でした。 setSoTimeoutはconnectに対しては効かないようです。 (OSはwindows2000です) Unixのconnect()にもtimeoutの引数はないですね。 JDK1.4のconnectはどうやってタイムアウトを実装しているのか 興味が湧いてきました。 以上です。 | ||||
|
投稿日時: 2004-01-30 15:40
ソースを呼んでいただければ分かるのですが、JDK1.4のtimout指定なしの
Sokect#connect()は、単にtimeout指定0でのconnect()にリダイレクト するだけです。ですので、残念ながらそのテストに意味はありません。 JDK1.3とJDK1.4では、PlainSocketImpl#socketConnect()の引数が変更 (タイムアウトが追加)になっていますので、そこを見ない限り実効のある 結論は得られないと思います。 SunのJVM実装の一部は、SCSLで公開されていると思いますので、興味があ れば入手してみてはいかがでしょうか。 | ||||
|
投稿日時: 2004-01-30 16:36
どうも、労多くて功少なしになりそうですね…
Kissingerさんのおっしゃるように、Socketのコンストラクタの呼び出しから 返ってくるまでを計時して、タイムアウトをシミュレートするようなProxyクラス を、Socketをラップする形で作るのが、よさそうです。 ということで、失礼しました。 | ||||
