• 締切済み

Socketの接続のタイムアウトを設定するには

JavaでSocket通信をしようとおもっています。 Socketはnewするときにconnectもしてしまいまうらしいので 妙なIPアドレスを指定したりして、応答がもどってこないと すべてそこで止まってしまうとおもうのですが、 Timeoutをかける方法はないのでしょうか。 setSoTimeoutというメソッドはreadのときとかStreamに関してしか かけられないということが分かりました。 Socketのコンストラクタの引数にSocketImplを指定して、 Socket.setSoTimeoutしてから SocketImpl.connectすれば大丈夫かな、とおもっていたのですが、 setSoTimeoutはreadにしか効かない、と明記してあったので、無駄ですよね。 どこかに情報がないかと検索エンジンでも探してみたのですが、 見つかりません。もしかしてタイムアウトを設定するのは 一般的な方法ではないのかとも思えてきました。 ずーーーーっと接続にしにいくのを待ちつづけるしかないのでしょうか。 どのような設計(というか使うクラス?)をするべきなのか、 思い当たるかたがいらっしゃいましたら教えていただけないでしょうか。 よろしくお願い致します(__)

  • Java
  • 回答数2
  • ありがとう数5

みんなの回答

  • ssr-y6
  • ベストアンサー率71% (5/7)
回答No.2

 以下は、別のスレッドでクライアントソケットを作って、それを監視/制御する一例です。 以前にそのような状況になったときがあり、そのときは以下の方法で対処できたと思います。 ありえないアドレスなどを指定して、ソケットを作るところで止まってしまったときには、 ソケットを作ろうとしたスレッドごと放棄しています。 import java.net.*; class clientthread extends Thread { private Socket Client; private ServerSocket Server; public boolean ConnectionFlag, BreakFlag; private int Port; private String HostName; public clientthread(String name, int port) throws Exception { super(); Port = port; HostName = name; ConnectionFlag = false; BreakFlag = false; }; public String GetConnectionData() { if (!ConnectionFlag) return("NotConnected"); return(Client.getRemoteSocketAddress().toString() + " : " + Integer.toString(Client.getLocalPort())); }; public void run() { try { Client = new Socket(InetAddress.getByName(HostName), Port); ConnectionFlag = true; if (BreakFlag) return; } catch(Exception ex) { System.out.println("<run>" + ex.toString()); }; }; } public class clientto { private static final int TimeoutTime = 10; public static void main(String args[]) { int i, j; clientthread ClientThread; try { for (j = 0; j < args.length; j += 2) { System.out.println(args[j]); ClientThread = new clientthread(args[j], Integer.parseInt(args[j + 1])); ClientThread.start(); for (i = 0; i < TimeoutTime; i ++) { if (ClientThread.ConnectionFlag) break; System.out.println("Connecting.." + i); try { Thread.sleep(100); } catch(Exception e) {}; }; if ((i == TimeoutTime) && (!ClientThread.ConnectionFlag)) ClientThread.BreakFlag = true; else ClientThread.join(); System.out.println(ClientThread.GetConnectionData()); }; } catch (Exception ex) { System.out.println("<main>" + ex.toString()); }; System.exit(0); }; }

  • a-kuma
  • ベストアンサー率50% (1122/2211)
回答No.1

Java は、あまり詳しくないので、考え方だけ。 ソケット通信をするクラスで、実際に connect するメソッド以外に、 タイムアウトをかけるメソッドを用意して、スレッドとして動かします。 Socket は、そのメソッドからも参照できるようにメンバーにして。 一定時間過ぎたところで、その Socket に対して close() をすると、 connect() 中でも、例外が飛んでくるはず。 正常に connect() できたのであれば、スレッドを止めるか、Socket を close() しないでちょうだいね、という情報をメンバーに設定する。 って感じではどうでしょうか? # java はあまり詳しくないですが、一応、ソフト屋さんです。 # 考え方はあっているはず。

tontoto
質問者

お礼

ありがとうございます。 やはりスレッドにして自力で実装しなくてはならないのですね…。 みんなやるから既にメソッドか テクニックが公開とかされていないものかな、 とおもったのですが、見つけられなくて…。 ありがとうございます。自分で組み込んで見ます(__)

関連するQ&A

  • InputStreamにたまったデータを消す方法

    InputStreamにたまったデータを消す方法 私は現在勉強のためにsocketプログラミングをJavaでしているのですが困った事があります。それはInputStreamからreadでデータを読み込んでも、読み込んだデータはStream内に消えずに残っているため、処理が複雑になってしまいます。何かflushのようなstreamにたまったデータを吐き出すメソッドはないのでしょうか?

    • ベストアンサー
    • Java
  • androidのsocketエラー

    androidのソケット通信プログラムを作成しています。 何度もソケットの接続・切断を繰り返していると、以下のエラーが発生します。 Socket.connect メソッド(接続)で発生しています。 socketは毎回.closeメソッドで切断しています。 このようになると、端末を再起動しない限りソケット接続を再度行なうことはできない模様です。このエラーの発生理由がわかりません。お詳しい方おられましたら何卒よろしくお願いします。 ちなみに利用しているandroid端末はKYL21(京セラ androidバージョン4.0.4)です。 01-09 09:06:46.418: W/System.err(29936): java.net.ConnectException: failed to connect to /192.168.10.12 (port 50000): connect failed: ENOBUFS (No buffer space available) 01-09 09:06:46.418: W/System.err(29936): at libcore.io.IoBridge.connect(IoBridge.java:114) 01-09 09:06:46.418: W/System.err(29936): at java.net.PlainSocketImpl.connect(PlainSocketImpl.java:192) 01-09 09:06:46.418: W/System.err(29936): at java.net.PlainSocketImpl.connect(PlainSocketImpl.java:460) 01-09 09:06:46.418: W/System.err(29936): at java.net.Socket.connect(Socket.java:838) 01-09 09:06:46.418: W/System.err(29936): at java.net.Socket.connect(Socket.java:791) 01-09 09:06:46.418: W/System.err(29936): at com.example.simple_test.Wifi_Service.Socket_Connect(Wifi_Service.java:2033) 01-09 09:06:46.428: W/System.err(29936): at com.example.simple_test.Wifi_Service$10.run(Wifi_Service.java:1938) 01-09 09:06:46.428: W/System.err(29936): Caused by: libcore.io.ErrnoException: connect failed: ENOBUFS (No buffer space available) 01-09 09:06:46.428: W/System.err(29936): at libcore.io.Posix.connect(Native Method) 01-09 09:06:46.428: W/System.err(29936): at libcore.io.BlockGuardOs.connect(BlockGuardOs.java:85) 01-09 09:06:46.428: W/System.err(29936): at libcore.io.IoBridge.connectErrno(IoBridge.java:127) 01-09 09:06:46.428: W/System.err(29936): at libcore.io.IoBridge.connect(IoBridge.java:112) 01-09 09:06:46.428: W/System.err(29936): ... 6 more

  • URLConnectionを用いたHTTPS通信時のタイムアウト設定

    現在java1.4.2.10を用いて、 指定のIDに紐づいたURLをDBから取得し、URLConnectionを用いて、取得したURL接続するといったプログラムを作成しております。 今回困っておりますのが、取得したURLがHTTPS通信だった場合のタイムアウト設定方法となります。 HTTPの場合は、下記のサイト http://www.slayers.nu/~kumasaka/Gyoumu/timeout.html を参考にさせていただき、なんとかなりましたが、HTTPSの場合には対応しておらず、困っております。 java1.5にはタイムアウト設定があるのですが、都合上1.5にはできず、 1.4.2で対応したく考えております。 System.setProperty に sun.net.client.defaultReadTimeout を設定することで getInputStream から抜けるまでの時間を制御できるようなのですが、これだと、1接続ごとにタイムアウト設定できません。 socket通信も考えたのですが、socket通信を用いた場合の、HTTPS通信の仕方もわからず、どなたかご教授のほどよろしくお願いいたします。

  • Javaの設計書について

    Javaの クラスやコンストラクタ、メソッドなどをわかりやすくできるExcelの設計書っぽいものってどこかにないでしょうか? 雛形みたいなものがみたいです。

    • ベストアンサー
    • Java
  • androidのSocketでの正常なリソース解放

    お世話になります、androidでsocket通信を行なうプログラム(Wifi経由)を作成しておりますが、周期的に何度も接続、通信、切断をくりかえしておりますと、ソケットの.connectをするところで以下のエラーが出ます。 java.net.ConnectException: failed to connect to /192.168.10.12 (port 50000): connect failed: ENOBUFS (No buffer space available) 周期動作としては、 ソケットの接続後、受信待ち状態はスレッド内でソケットのInputStreamの.read()で行い(読み取ることができるまでブロックされるメソッド)、送信は、別のスレッドを起こしてソケットのOutputStreamでのflush()で送信しています。ある周期的タイミングで切断の手順を踏みます。 エラーの内容からして、切断するメソッド発行時にちゃんとリソースが解放されていない?のではないかと考えます。今、私がソケットを閉じよとする際に発行しているメソッドは以下になります(順同) (1)ソケットのOutputStream.close (2)ソケットのInputStream.close (3)ソケット.close 正常にソケット回りのリソースを解放する手順としてソケットの閉じる方法は間違っていますでしょうか? ちなみに、このエラーが出た後はインターネットへの接続も不可状態になり、端末を再起動しないと復帰しません。 大変困っております、お詳しい方おられましたら、よろしくお願いします。

  • Winsock Connnect タイムアウト について

    OS :WinXP SP3 言語:VC++ 2005 Winsock2の通信モジュールを開発中です。 connectのタイムアウト方法をネットで調べて下記の関数を 作成(完全引用)したのですが、上手くいきません。 WSAWaitForMultipleEventsでイベントが発生していない (接続先が存在しない)のですが処理が返ってきてしまいます。 何か間違っているのでしょうか?ご回答、宜しくお願い致します。 ----------------------------------------------------------------BOOL connect2 ( SOCKET aSock, char* dwAddr, int wPort, int nTimeout ) { int liRet, liErr, liRetflag = FALSE; unsigned long lulAddr = inet_addr ( dwAddr ); WSAEVENT hEvent; DWORD dwRet; WSANETWORKEVENTS Events; sockaddr_in Addr; // イベント作成 hEvent = WSACreateEvent(); if ( hEvent == WSA_INVALID_EVENT ) { return FALSE; } // イベント型に(自動的にノンブロッキングになる) liRet = WSAEventSelect( aSock, hEvent, FD_CONNECT ); if( liRet == SOCKET_ERROR ) { WSACloseEvent( hEvent ); return FALSE; } // 接続 ZeroMemory( &Addr, sizeof( Addr ) ); Addr.sin_family = AF_INET; Addr.sin_port = htons( ( unsigned short )wPort ); Addr.sin_addr.s_addr = lulAddr; if ( connect( aSock, ( struct sockaddr* )&Addr, sizeof( Addr ) ) == SOCKET_ERROR ) { liErr = WSAGetLastError(); // WSAEWOULDBLOCKの時はまだ接続されていないので続ける if ( liErr != WSAEWOULDBLOCK ) { goto END; } } *** ↓ここですぐ返ってきてしまい、WSA_WAIT_TIMEOUTにならない *** // イベント発生待機 dwRet = WSAWaitForMultipleEvents( 1, &hEvent, FALSE, 60000, FALSE ); // dwRetがWSA_WAIT_EVENT_0以外でエラー // dwRetがWSA_WAIT_TIMEOUTの時タイムアウト if ( dwRet != WSA_WAIT_EVENT_0 ) { goto END; } // どのイベントが発生したか liRet = WSAEnumNetworkEvents( aSock, hEvent, &Events ); if( liRet == SOCKET_ERROR ) goto END; // Events.iliErrorCode[FD_CONNECT_BIT]が0の場合成功 if( ( Events.lNetworkEvents & FD_CONNECT ) && Events.iErrorCode[FD_CONNECT_BIT] == 0 ) { liRetflag = TRUE; } END: // イベント型を終了 WSAEventSelect( aSock, NULL, 0 ); WSACloseEvent( hEvent ); // ブロッキングに戻す(必要なら) dwRet = 0; ioctlsocket( aSock, FIONBIO, &dwRet ); return liRetflag; } ----------------------------------------------------------------

  • javaのメソッドの引数で、クラスの配列を指定する

    javaのメソッドの引数で、クラスの配列を指定する事は可能なのでしょうか? 受け取るメソッドでは引数の所に何と書けば良いのでしょうか? 教えてください!

    • ベストアンサー
    • Java
  • socketでのバイナリファイルの扱い方

    javaのsocketを用いてファイルの送信サーバ、受信クライアントを作成しているのですが テストプログラムとしてスレッド化せずに送信・受信部のみ作りました。 症状はバイナリデータの転送がうまくできないことです。ソースを抜粋すると サーバ側で BufferedOutputStream out = new BufferedOutputStream(socket.getOutputStream());//socketはSocketクラス BufferedInputStream in1 = new BufferedInputStream( new FileInputStream("test1.bmp")); BufferedInputStream in2 = new BufferedInputStream( new FileInputStream("test2.bmp")); while( (c = in1.read() ) != -1 ){   out.write(c); } while( (c = in2.read() ) != -1 ){   out.write(c); } クライアント側で BufferedOutputStream out1 = new BufferedOutputStream( new FileOutputStream("test1.out.bmp") ); BufferedOutputStream out2 = new BufferedOutputStream( new FileOutputStream("test2.out.bmp") ); BufferedInputStream in = new BufferedInputStream( s.getInputStream() ); while( ( c=in.read() ) != -1 ){   out1.write(c); } while( ( c=in.read() ) != -1 ){   out2.write(c); } とやっています。 クライアント側で1回目のin.readを抜けるときにはサーバ側は既に2回のwriteを終わっているようで ファイルはtest1.out.bmpにマージされていました。 サーバ側の1回目のwriteのオブジェクトがcloseしていないことが原因だと思い1回目のwriteが終わった時点でout.close()とした のですがそうやるとsocketも閉じてしまいsocket closeのエラーが生じてしまいました。 このようにならず1本のコネクションでバイナリのデータを複数送信する方法をご存知でしたら教えてください。 [環境] win2ksp1a,j2sdk1.4.1_03,java経験4ヶ月程度

  • socketを使用したスクリプトがうまく動きません

    お世話になります。教えて!gooを初めて利用する者です。 Perlは本などを見ながら何とか動かせるレベルです。 この度、socketを使って他サイトを読み込む実験をしてみたところ、以下のコードでGoogleのトップページは読み込めましたがYahoo!のトップは何度やってもちゃんと読み込めません。 失敗している部分は、相対パス指定になっている部分のようです。 リンクや画像など、「http://www.yahoo.co.jp/~」となるはずのところが、「http://127.0.0.1/~」となってしまっています。 また、LWPモジュールというものも試してみましたが、こちらはGoogleのトップの読み込みも失敗しました。症状は上と同じです。 コードは本や有名サイトからそのまま引用してもダメで、多少いじってもやはりダメでした。 一人で解決するのは限界だと思いましたので、分かる方いらっしゃいましたらご助言をお願いいたします。 (試したコードの例↓) use Socket; $addr = (gethostbyname("www.google.co.jp"))[4]; $name = pack("S n a4 x8", 2, 80, $addr); socket(S, PF_INET, SOCK_STREAM, 0) || die "socket"; connect(S, $name) || die "connect"; binmode(S); select(S); $| = 1; select(STDOUT); print S "GET / HTTP/1.0\r\n\r\n"; while (<S>) { print; } close(S);

  • Socketに関して

    SocketでURLで指定されたバナーを一旦ダウンロードし、 画像サイズを取得するプログラムなのですが、 以下のソースでは、画像が存在するURLを指定しても 「バナ-画像が存在しません。バナ-URLを確認してください。」 となってしまいます。 どこが不具合なのか分かる方がいらっしゃれば教えて頂けないでしょうか? サーバーは「land.to」です。 use Socket; sub GetBannerSize{ #バナ-サイズ取得(sock接続) my ( $url ) = @_; my ( $host, $port, $path, $dir, $file, $base, $ext, $width, $height, $ipaddr, $sockaddr, $tmpimg, $data ); $url =~ /(http:)?(\/\/)?([^:\/]*)?(:([0-9]+))?(\/.*)?/; $host = $3; if ($host eq "" || $host eq $ENV{'SERVER_NAME'}) {$host = 'localhost';} $path = $6; if ($path eq "") {$path = '/';} if ($path =~ /(.*)\/(.*)/) { $dir = $1.'/'; $file = $2; } else { $dir = './'; $file = $path; } if ($file =~ /(.*)\.(.*)/) { $base = $1; $ext = $2; } else { # 拡張子なし $base = $file; $ext = ""; } $port = getservbyname("http", "tcp"); $ipaddr = inet_aton($host) || &error("host($host) not found."); $sockaddr = pack_sockaddr_in($port, $ipaddr); socket(SOCK, PF_INET, SOCK_STREAM, 0) || &error("socket error."); connect(SOCK, $sockaddr) || &error("connect $host $port error."); select(SOCK); $|=1; select(STDOUT); print SOCK << "END_OF_DOC"; GET $path HTTP/1.0 Host:$host Connection:close END_OF_DOC while(<SOCK>){ last if m/^\r\n$/; } $tmpimg = ""; if ($ext eq "gif") { $tmpimg = "./temp/tmp.gif"; }elsif ($ext eq "jpg" || $ext eq "jpeg") { $tmpimg = "./temp/tmp.jpg"; }elsif ($ext eq "png") { $tmpimg = "/temp/tmp.png"; }else{ &error("画像形式が正しくありません。"); } open(OUT,">$tmpimg"); while (<SOCK>) { if ($_ =~ /<HTML>/i) { &error("バナ-画像が存在しません。バナ-URLを確認してください。"); } print OUT $_; } close(OUT); close SOCK; $width = 0; $height = 0; if ($ext eq "gif") { open(IN,"$tmpimg") || return (0,0); binmode(IN); sysread(IN,$data,10); close(IN); if ($data =~ /^GIF/) { $data = substr($data,-4); } $width = unpack("v",substr($data,0,2)); $height = unpack("v",substr($data,2,2)); } elsif ($ext eq "jpg" || $ext eq "jpeg") { local($t, $m, $c, $l); open(IN,"$tmpimg") || return (0,0); binmode(IN); read(IN, $t, 2); while (1) { read(IN, $t, 4); ($m, $c, $l) = unpack("a a n", $t); if ($m ne "\xFF") { $W = $H = 0; last; } elsif ((ord($c) >= 0xC0) && (ord($c) <= 0xC3)) { read(IN, $t, 5); ($height, $width) = unpack("xnn", $t); last; } else { read(IN, $t, ($l - 2)); } } close(IN); } elsif ($ext eq "png") { open(IN,"$tmpimg") || return (0,0); binmode(IN); read(IN, $data, 24); close(IN); $width = unpack("N", substr($data, 16, 20)); $height = unpack("N", substr($data, 20, 24)); } unlink $tmpimg; return( $width, $height ); }