• 締切済み

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 正常にソケット回りのリソースを解放する手順としてソケットの閉じる方法は間違っていますでしょうか? ちなみに、このエラーが出た後はインターネットへの接続も不可状態になり、端末を再起動しないと復帰しません。 大変困っております、お詳しい方おられましたら、よろしくお願いします。

みんなの回答

  • uyama33
  • ベストアンサー率30% (137/450)
回答No.3

お役に立てるかどうか分かりませんが、 RFC5802 で、 For the SCRAM-SHA-1/SCRAM-SHA-1-PLUS SASL mechanism, servers SHOULD announce a hash iteration-count of at least 4096. Note that a client implementation MAY cache ClientKey&ServerKey (or just SaltedPassword) for later reauthentication to the same service, as it is likely that the server is going to advertise the same salt value upon reauthentication. This might be useful for mobile clients where CPU usage is a concern. と書いてあるのを、見つけました。

回答No.2

No.1です。 connectエラー発生時にTIME_WAIT状態のものがないことが確認できたのだったら、 この件とは別の問題なのだと思いますが、この質問をするなら、どれくらいの時間間隔で 繰り返しているかだけでなく、エラーが発生するのがどれくらいの回数を繰り返して なのか、あるいはどれくらいの時間を繰り返してなのかもちゃんと書いた方がよいと 思います。 1分間隔でconnectしているのだとしたら、1時間繰り返しても60コネクション程度 なので、もし1時間程度で発生するのだったら、メモリ不足になるほどメモリを 消費しているという可能性は低いかもしれません。もちろん1コネクション生成に あたってアプリが膨大なメモリを使っていて、それがうまく解放されてないのでしたら メモリ不足になる場合もあると思います。そうであればメモリ使用量を監視すれば なにかわかると思います。 また、繰り返し周期を2倍遅くしたら、エラーが発生し始める時間も2倍遅くなるのか、 それとも回数に依らず一定時間でエラーが発生し始めるのかを試してみると、 エラー発生要因を探る手がかりになると思います。 あと、ソケット切断後にwifiを切断しているというのも何のためにどのようにしている のかよくわかりませんでした。 これってwifiの設定をあなたのアプリが勝手にOFFにするということなのでしょうか? なぜアプリが勝手にwifiの設定をOFFにするのかよくわからなかったので、じゃあwifiを 切断しなかったらどうなるのかというのも試してみた方がよいと思いました。

回答No.1

TCP/IPプロトコルでは、切断を開始した側は切断手順の最後に必ず タイムアウト待ち(TIME_WAIT状態)になることをご存知ですか? http://www.atmarkit.co.jp/ait/articles/0402/13/news096_3.html の「TCPの状態遷移図」を参照してください。 これは、OutputStreamだけを先に閉じるハーフ・クローズ手順でも同じです。 http://www.geocities.jp/taka_owl2005/job/UNIX/network/tcp_spe.html#finish も参考にしてください。 このTIME_WAIT時間はシステムによってデフォルト値が異なりますが、 Windowsで240秒、CentOSで60秒です。Androidがどうなっているか知りませんが おそらくLinux系で60秒くらいだと思います。 コネクションの接続/切断周期がこれより短いのであれば、TIME_WAIT状態の コネクションがどんどん増えて行き、確実にリソース不足になります。 このTIME_WAIT時間の設定を自分の接続/切断周期以下にすればリソース不足は 解消されると思いますが、この値はネットワーク状態に応じて決めるべきもの であり、アプリの都合で変えるべきものではありません。 根本的には、頻繁な接続/切断の繰り返しを避けるよう設計する必要があります。

ojinnjinn
質問者

補足

丁寧なご回答ありがとうございます。 私のほうでもTIME_WAITについて疑ってみましたが、おっしゃるとおりandroidのタイムウエイトは60秒であるようでした。(実際にnetstatというアプリで監視してみますと、TIME_WAIT状態になったものは60秒後に消えました) 私の作っているシステムは60秒周期で1つのソケットをandroid端末側から接続して、双方通信して、android端末側から切断するという動作を行なっております。ちなみにWifiの通信の切断も ソケット切断の3秒後に実施しています。 60秒周期で動作を繰り返しておりますので、TIME_WAIT状態のものがたくさん生成されている状態は考えにくい+実際にENOBUFSが起こっている状態でnetstatアプリで確認したところ、TIME_WAITがたくさんある状態ではありません(むしろLISTENなプロセスが1つあるだけ、のような状態です) 他に疑わしい事柄はありますでしょうか? ソケットプロセスがTIME_WAITにある状態でWifiを切断するのがまずい?とかあるのでしょうか・・・。

関連するQ&A

  • 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

  • java socketエラーについて

    javaでソケット接続するプログラムを作成しています。ソケット接続の以下のエラーがたまに発生するのですが、このエラーが出た際、回避方法がわかりません。どのようにしたら再度ソケット接続を行なえるのでしょうか? 以下エラー内容です。 java.net.ConnectException: failed to connect to /192.168.10.12 (port 50000): connect failed: ENOBUFS (No buffer space available) お詳しい方、よろしくお願いします!

    • ベストアンサー
    • Java
  • javaのsocketインスタンスについて

    javaでソケット接続するプログラムを作成しています。 socketを.closeした場合、このsocketインスタンスのシステムリソースは開放されるのでしょうか? お詳しい方おられましたらよろしくお願いします。

  • DBを扱う上でのclose()メソッドの必要性

    JavaでDBにアクセスする為の勉強中です。 使用しているクラスは Connection、Statement、ResultSet でそれぞれfinallyの部分でclose()メソッドを呼んでいます 例えばこのときStatementのJavaDocでclose()メソッドの説明を読むと >自動的にクローズされるときに Statement オブジェクトのデータベースと JDBC リソースが解放されるのを待つのではなく、ただちにそれらを解放します。 とあり、該当のメソッドを呼ばなくても、リソースは解放されるようですが、ただちに解放する必要性はどこにあるのでしょうか? 検索結果で表示されるサイト等も大半はclose()が書かれていますが、 おまじない的な話しか載ってるのを見る程度でした。

  • PerlでSocketを閉じずに再利用する方法

    インターネット上の情報を参考に作成したCGIでPerlのソケットを用いて通信を行っておりますが、CGIが呼び出されるたびに以下のような動作を行っております。 ソケット生成 -> ソケット接続 -> HTTP通信 -> ソケット切断 このうち、ソケットの接続におおよそ200ミリ秒ほどかかり、このレイテンシを減らすため、ソケットはCGIが呼び出されるたびに生成、接続するのではなく、最初からセッションを張った状態で、CGIが呼び出されるとHTTP通信部分のみを行うようにすることはできますでしょうか。 現在試したこととして、1回目の呼び出しでソケットをクローズせずに処理を終了し、2回目でソケットの生成、接続をせずに直接HTTP通信をしようとしてもうまくいきませんでした。 Perl、ネットワークプログラミング初心者なもので恐縮ですが、何卒よろしくお願いいたします。

    • ベストアンサー
    • Perl
  • 初歩的なソケット通信(java)

    初歩的なソケット通信(java) javaのソケット通信プログラムについて質問させて頂きます。まだまだ基礎の段階なのですが、詰まってしまたので、良かったら教えてください。 以下プログラムコード ------------------------------------- //サーバー側 import java.net.*; import java.io.*; public class Server { static int port = 12345; public static void main(String[] args) { try{ //サーバソケットの作成 ServerSocket ssoc = new ServerSocket(port); //メインループ while(true){ try{ System.out.println("クライアントからの接続を"+ port +"で待ちます"); Socket soc = ssoc.accept(); System.out.println(soc.getInetAddress().getHostName()+"から接続を受けました"); //処理をスレッドに任せます new Connect(soc); }catch(IOException e1){ e1.printStackTrace(); } } }catch(IOException e2){ e2.printStackTrace(); } } } class Connect extends Thread{ private Socket socket = null; public Connect(Socket socket){ this.socket = socket; //スレッド開始 this.start(); } public void run(){ try{ //出力ストリームを取得 OutputStream os = socket.getOutputStream(); PrintWriter out = new PrintWriter(os,true); //入力ストリームを取得 InputStream is = socket.getInputStream(); InputStreamReader isr = new InputStreamReader(is); BufferedReader in = new BufferedReader(isr); String inputLine; while((inputLine = in.readLine()) != null){ //System.out.println(inputLine); out.println(inputLine); } System.out.println("処理が終わったので接続を切ります"); in.close(); out.close(); socket.close(); }catch(Exception e1){ try{ socket.close(); }catch(Exception e2){ e2.printStackTrace(); } } } }

  • システムリソース

     最近ネット等をしていると、突然切断されてしまいます。インストールしてあるゲーム等も起動しません。おきにいりに登録してある何をクリックしても、ぺージを表示できません、もしくは、ショートカットエラーを開けません、と表示されます。切断された後再起動させればまた接続されます。いろいろ調べた結果、どうやらシステムリソースが不足しているらしいのです。なぜ不足したのか、それは最近○ートンインターネットセキュリティ2003をインストールしたのが原因かもしれません。システムリソースはショ-トカットアイコンを減らしたり壁紙を無くせば回復するそうですが、あまり変化が見られません。OSがXPでこのような状態を改善する方法を教えてください。

  • SocketのSend関数でのCLOSEの検知 [Linux]

    Linux環境でSocket(dm:PF_INET,type:SOCK_STREAM)を使用しての、 Client&ServerプログラムをCで作成しているのですが、 そこでのSend関数の使い方についてご助力ください。 Client&Serverプログラムは下記のような動きをします。 [Client] ServerへConnectした後、複数のDataを数秒間隔でServerへ 送信(send関数使用)します。受信(recvやread関数等)は、 一切行いません。 [Server] ClientからのConnectを受け付けた後、Clientから受信(recv関数 使用)したDataを標準出力へ表示する。送信(sendやwrite関数 等)は、一切行いません。 さて、ここでもしClientプログラムがCloseを発行したり、マシン DOWN等の理由でConnectionが切断され、Server側のSocketが CLOSE_WAIT状態になった場合、Bufferに溜まっていたDataを すべて受けきった後、recv関数が0を返してくれるので 相手が終了したことがわかります。 ここからが質問のMainです。 では、もしServerプログラムがCloseを発行したり、マシン DOWN等の理由でConnectionが切断され、Client側のSocketが CLOSE_WAIT状態になっても、CLOSE_WAIT直後のsend関数が なぜか正常に処理されてしまいます。無論このDataは、 Server側は受け取りません。この次のsend関数実行時に EPIPEが返ってくるので、ここでようやくSocketが切断された ことが判ります。 これを何とかCLOSE_WAIT状態になった直後から、send関数で 切断を検知できるようにできないでしょうか。 よろしくお願いします。 以上

  • netstat、netstat -a のState

    netstat オプションなしと、netstat -a の表示されるStateの種類の違いについて教えてください(Linux) # netstat # netstat -a を実行したときに表示されるStateの種類の違いは、オプションなしは下記StateのLISTEN以外が表示対象で、-a オプション指定時は下記Stateの全てが表示対象である認識で間違っていないでしょうか。 State ESTABLISHED ソケットは確立した接続状態にある。 SYN_SENT ソケットは接続を確立しようと試みている。 SYN_RECV 接続要求をネットワークから受信している。 FIN_WAIT1 ソケットはクローズされており、接続は切断中である。 FIN_WAIT2 接続はクローズされ、ソケットはリモート側からの切断を待っている。 TIME_WAIT ソケットは、クローズ後にリモートからの切断が再送されるのを待っている。 CLOSED ソケットは使用されていない。 CLOSE_WAIT リモート側は既に切断され、ソケットがクローズされるのを待っている。 LAST_ACK リモート側は既に切断され、ソケットもクローズされている。 確認 (acknowledgement) を待っている。 LISTEN ソケットは接続待ち (listen) である。 このようなソケットは、 --listening (-l) または --all (-a) オプションを指定しない限り、出力には含まれない。 CLOSING 両方のソケットが切断されているが、まだ全てのデータが送られていない。 UNKNOWN ソケットの状態は不明である。

  • 共有お絵かきシステムの同期の取り方について

    現在、共有ホワイトボードになるものを作っています。 今は以下のような方法で同期をとろうとしています。 クライアントからサーバへはソケットで接続し、サーバ側で接続があれば別スレッドで入力を待ち続けます。 スレッドを新しく走らせる時点でクライアントのソケットに対するOutputStreamを配列に入れ、複数のクライアントの出力先の管理をします。 各スレッド毎に入力(描画情報)があると、上記のOutputStreamの配列に対してその要素数分だけfor文をまわし、受け取った情報を接続中のクライアントに出力する。 といった同期の取り方をしています。 しかし、各クライアントからの描画情報はとても多く、クライアントが3人以上になるとすぐに固まってしまったり、クライアント側で情報がごちゃごちゃになり期待通りの描画がされなかったりといったことになります。 共有ホワイトボード等でお絵かき情報の同期の取り方について何か良い考え方はありませんでしょうか?

    • ベストアンサー
    • Java

専門家に質問してみよう