ソケットのTCPキープアライブ時間を2時間から10分程度の時間に短縮したいと思います。私はsocket.setKeepAlive(true)でキープアライブを使用させることができますが、キープアライブパケットを送信する前にどのように時間を制御できますか?Androidでキープアライブタイムアウトを設定するにはどうすればよいですか?
私はNDKを使用していた場合、これを行うことができたようですが、このコードをjarとして配布したいので、それは私にとって理想的ではありません。
ソケットのTCPキープアライブ時間を2時間から10分程度の時間に短縮したいと思います。私はsocket.setKeepAlive(true)でキープアライブを使用させることができますが、キープアライブパケットを送信する前にどのように時間を制御できますか?Androidでキープアライブタイムアウトを設定するにはどうすればよいですか?
私はNDKを使用していた場合、これを行うことができたようですが、このコードをjarとして配布したいので、それは私にとって理想的ではありません。
これはあまりにも明白な答えです。あなたの特定のケースではオプションではありませんが、10分ごとに1つのスローアウェイバイトを(どちらの方向にも)送信することで、独自のキープアライブを実装できます。
のAndroidは、Linuxをベースにしており、Linuxはjava.net.SocketOptions
インターフェースによってラップさsetsocketopt()
機能、経由TCP_KEEPIDLE
とTCP_KEEPINTVL
ソケットオプションをサポートしています。 java.net.SocketImpl
はSocketOptions
を実装し、java.net.Socket
はSocketImpl
をラップします。私が知らないのは、与えられたSocket
オブジェクトのSocketImpl
にアクセスすることができるかどうかということです。
Socket.setSocketImplFactory()
を使用して、Socket
オブジェクトのSocketImpl
インスタンスを作成する独自のカスタムSocketImplFactory
クラスを実装することができます。そうすれば、あなたの工場は、TCP_KEEPIDLE
のSocketOptions.setOption()
と、あなたのアプリケーションが作成するソケットのTCP_KEEPINTVL
を呼び出すことができます。
アンドロイドの場合はTCP_KEEPIDLEとTCP_KEEPINTVLのヒントを+1します。しかし、[this](http://stackoverflow.com/a/1480246/3574669)は、システムレベルのキープアライブではなくアプリケーションレベルの実装に投票しています。あなたの意見は何ですか? – ajay
この質問は、すべてのプラットフォームがTCP秒の一部としてサポートするシステムレベルのキープアライブに関するものです(すべてのプラットフォームで間隔の設定がサポートされているわけではありません)。アプリケーションレベルのキープアライブはプロトコルに依存しており、多くのプロトコルはアプリケーションレベルのキープアライブをサポートしていません。 ** IF **アプリケーションレベルのキープアライブが可能で、是非それを使用してください。しかし、必要に応じてシステムレベルのキープアライブに戻ってください。 –
私はそれが悪いネットワークの状態(無線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.SocketImpl
でjava.net.SocketImpl
のインスタンスは、現在のSDKバージョンでfd
部材が有するTCP_KEEPIDLE
、TCP_KEEPINTVL
とTCP_KEEPCNT
現在のSDKバージョンで同じ値 (4
、5
と6
)を有しとすべてのアンドロイドデバイス/アーキテクチャ少なくとも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_KEEPIDLE
、TCP_KEEPINTVL
およびTCP_KEEPCNT
は、2.2.3 r2以降のアンドロイドバージョンとすべてのアーキテクチャで同じ値を持つようです。これは、例えば検証することができる。リポジトリandroid platform/ndkにfind . -name tcp.h | xargs grep -ho "TCP_KEEP\w\+\s\+\d\+" | sort | uniq -c
を実行してください。
erm ...私が推測するように簡単です... – Bharel
ええ、私はおそらくそれをやり遂げるつもりです。私はそれがバッテリー寿命にそれほど課税されていると聞いています。うまくいけば妥当なサーバー側のキープアライブを設定できます。 – lacker