2011-07-03 44 views
6

ソケットのTCPキープアライブ時間を2時間から10分程度の時間に短縮したいと思います。私はsocket.setKeepAlive(true)でキープアライブを使用させることができますが、キープアライブパケットを送信する前にどのように時間を制御できますか?Androidでキープアライブタイムアウトを設定するにはどうすればよいですか?

私はNDKを使用していた場合、これを行うことができたようですが、このコードをjarとして配布したいので、それは私にとって理想的ではありません。

答えて

1

これはあまりにも明白な答えです。あなたの特定のケースではオプションではありませんが、10分ごとに1つのスローアウェイバイトを(どちらの方向にも)送信することで、独自のキープアライブを実装できます。

+0

ええ、私はおそらくそれをやり遂げるつもりです。私はそれがバッテリー寿命にそれほど課税されていると聞いています。うまくいけば妥当なサーバー側のキープアライブを設定できます。 – lacker

4

のAndroidは、Linuxをベースにしており、Linuxはjava.net.SocketOptionsインターフェースによってラップさsetsocketopt()機能、経由TCP_KEEPIDLETCP_KEEPINTVLソケットオプションをサポートしています。 java.net.SocketImplSocketOptionsを実装し、java.net.SocketSocketImplをラップします。私が知らないのは、与えられたSocketオブジェクトのSocketImplにアクセスすることができるかどうかということです。

Socket.setSocketImplFactory()を使用して、SocketオブジェクトのSocketImplインスタンスを作成する独自のカスタムSocketImplFactoryクラスを実装することができます。そうすれば、あなたの工場は、TCP_KEEPIDLESocketOptions.setOption()と、あなたのアプリケーションが作成するソケットのTCP_KEEPINTVLを呼び出すことができます。

+0

アンドロイドの場合はTCP_KEEPIDLEとTCP_KEEPINTVLのヒントを+1します。しかし、[this](http://stackoverflow.com/a/1480246/3574669)は、システムレベルのキープアライブではなくアプリケーションレベルの実装に投票しています。あなたの意見は何ですか? – ajay

+0

この質問は、すべてのプラットフォームがTCP秒の一部としてサポートするシステムレベルのキープアライブに関するものです(すべてのプラットフォームで間隔の設定がサポートされているわけではありません)。アプリケーションレベルのキープアライブはプロトコルに依存しており、多くのプロトコルはアプリケーションレベルのキープアライブをサポートしていません。 ** IF **アプリケーションレベルのキープアライブが可能で、是非それを使用してください。しかし、必要に応じてシステムレベルのキープアライブに戻ってください。 –

8

私はそれが悪いネットワークの状態(無線LAN /モバイル)の下にあるかもしれないので、キープアライブは、特にモバイルデバイス上で、アプリレベルごとをタイムアウト設定できるように非常に重要かもしれないと思います。 アプリがのデータを送信していないのに、の永続的接続を使用している場合、ソケットは、tcpキープアライブプローブを送信しない限り、接続が失われたかどうかを検出しません()。このオプションは通常setsockopt(2)コールで設定できますが、android sdkはsetKeepAlive(boolean)オプションのみを提供します。スタック内の深いところでは、関数libcore.io.ForwardingOs.setsockoptInt(...)が呼び出されます。これは直接で利用できないであり、必要なファイル記述子もありません。 Javaリフレクションを使用すると、キープアライブタイムアウトを設定することが可能です。とにかく、e。

private final static int SOL_TCP = 6; 

private final static int TCP_KEEPIDLE = 4; 
private final static int TCP_KEEPINTVL = 5; 
private final static int TCP_KEEPCNT = 6; 

protected void setKeepaliveSocketOptions(Socket socket, int idleTimeout, int interval, int count) { 
    try { 
    socket.setKeepAlive(true); 
    try { 
     Field socketImplField = Class.forName("java.net.Socket").getDeclaredField("impl"); 
     socketImplField.setAccessible(true); 
     if(socketImplField != null) { 
     Object plainSocketImpl = socketImplField.get(socket); 
     Field fileDescriptorField = Class.forName("java.net.SocketImpl").getDeclaredField("fd"); 
     if(fileDescriptorField != null) { 
      fileDescriptorField.setAccessible(true); 
      FileDescriptor fileDescriptor = (FileDescriptor)fileDescriptorField.get(plainSocketImpl); 
      Class libCoreClass = Class.forName("libcore.io.Libcore"); 
      Field osField = libCoreClass.getDeclaredField("os"); 
      osField.setAccessible(true); 
      Object libcoreOs = osField.get(libCoreClass); 
      Method setSocketOptsMethod = Class.forName("libcore.io.ForwardingOs").getDeclaredMethod("setsockoptInt", FileDescriptor.class, int.class, int.class, int.class); 
      if(setSocketOptsMethod != null) { 
      setSocketOptsMethod.invoke(libcoreOs, fileDescriptor, SOL_TCP, TCP_KEEPIDLE, idleTimeout); 
      setSocketOptsMethod.invoke(libcoreOs, fileDescriptor, SOL_TCP, TCP_KEEPINTVL, interval); 
      setSocketOptsMethod.invoke(libcoreOs, fileDescriptor, SOL_TCP, TCP_KEEPCNT, count); 
      } 
     } 
     } 
    } 
    catch (Exception reflectionException) {} 
    } catch (SocketException e) {} 
} 

これはが満たされ少なくともまで以下要件動作:

  • libcore.io.ForwardingOs.setsockoptInt/4が現在のSDKバージョン
  • java.net.Socketに存在するでimpl部材を有する、このようなG現在のSDKバージョン
  • java.net.Socket->impl現在のSDKバージョン
  • java.net.SocketImpljava.net.SocketImplのインスタンスは、現在のSDKバージョンでfd部材が有する
  • TCP_KEEPIDLETCP_KEEPINTVLTCP_KEEPCNT現在のSDKバージョンで同じ値 (456)を有しすべてのアンドロイドデバイス/アーキテクチャ少なくとも4.0.1/November 2011までの最近のバージョン5.1.1 r9からアンドロイドのバージョンのために真であると思わ

platform/libcoreリポジトリのluni/src/main/java/libcore/io/Os.java,luni/src/main/java/java/net/Socket.javaおよびluni/src/main/java/java/net/SocketImpl.javaを参照してください。 TCP_KEEPIDLETCP_KEEPINTVLおよびTCP_KEEPCNTは、2.2.3 r2以降のアンドロイドバージョンとすべてのアーキテクチャで同じ値を持つようです。これは、例えば検証することができる。リポジトリandroid platform/ndkfind . -name tcp.h | xargs grep -ho "TCP_KEEP\w\+\s\+\d\+" | sort | uniq -cを実行してください。

+0

erm ...私が推測するように簡単です... – Bharel

関連する問題