2011-07-03 4 views
6

소켓에서 TCP keepalive 시간을 낮추고 싶습니다. 열 시간이 2 시간에서 10 분 정도입니다. keepalive를 socket.setKeepAlive (true)와 함께 사용할 수는 있지만 keepalive 패킷을 보내기 전에 시간을 어떻게 제어 할 수 있습니까?안드로이드에서 keepalive timeout을 설정하는 방법은 무엇입니까?

NDK를 사용하는 경우이 작업을 수행 할 수 있지만이 코드를 항아리로 배포하려고하므로 이상적이지 않습니다.

답변

1

이것은 너무 분명한 답변입니다. 그것은 당신의 특정 경우에 대한 옵션이 아니에요] 물론 당신은 10 분 간격으로 1 개의 쓰레기 처리 바이트를 보내어 자신의 keepalive를 구현할 수 있습니다.

+0

그래, 아마 그 일을 끝내야 겠어. 그래도 배터리 수명에 더 부담 스럽다고 들었습니다. 잘하면 합리적인 서버 측 keepalive를 설정할 수 있습니다. – lacker

4

Android는 Linux를 기반으로하며 Linux는 setsocketopt() 함수를 통해 인터페이스로 감싸 인 소켓 옵션을 TCP_KEEPIDLETCP_KEEPINTVL으로 지원합니다. java.net.SocketImplSocketOptions을 구현하고 java.net.SocketSocketImpl을 래핑합니다. 내가 모르는 것은 주어진 Socket 오브젝트의 SocketImpl에 액세스 할 수 있는지 여부입니다. 당신이 일을 시도 할 수 무엇

Socket 개체에 대한 SocketImpl 인스턴스를 생성 할 책임이 사용자 정의 SocketImplFactory 클래스를 구현하는 Socket.setSocketImplFactory()를 사용합니다. 그렇게하면 공장에서 앱이 생성하는 모든 소켓에 대해 TCP_KEEPIDLETCP_KEEPINTVL에 대해 SocketOptions.setOption()을 호출 할 수 있습니다.

+0

안드로이드의 경우 TCP_KEEPIDLE 및 TCP_KEEPINTVL 사용에 대한 힌트는 +1. 그러나 [this] (http://stackoverflow.com/a/1480246/3574669)는 시스템 레벨 킵 얼라이브가 아닌 애플리케이션 레벨의 구현을 위해 투표하고 있습니다. 당신 의견은 무엇입니까? – ajay

+0

이 질문은 특히 모든 플랫폼이 TCP 초의 일부로 지원하는 시스템 수준의 Keepalive에 대한 질문이었습니다 (모든 플랫폼이 간격 설정을 지원하지는 않지만). 응용 프로그램 수준의 Keepalive는 프로토콜에 따라 다르며 많은 프로토콜은 응용 프로그램 수준의 Keepalive를 지원하지 않습니다. ** ** 응용 프로그램 수준의 Keepalive가 가능하면 꼭 사용하십시오. 그러나 필요한 경우 시스템 수준의 Keepalive로 되돌아갑니다. –

8

나는 그것이 잘못된 네트워크 상태 (와이파이/모바일)에서 수 있기 때문에 매우 중요에서, 킵 얼라이브 특히 모바일 장치에 응용 프로그램 레벨 당 을 제한 시간 설정 할 수있을 것 같아요 . 앱이 어떤 데이터 ()도 보내지 않지만 지속적인 연결을 사용하는 경우 소켓은 tcp 연결 유지 프로브를 전송하지 않는 한 연결이 끊어 졌는지 여부를 감지하지 않습니다 (). 이 옵션을 설정하는 것은 대개 setsockopt(2) 호출을 통해 가능하지만 Android sdk는 setKeepAlive(boolean) 옵션 만 제공합니다. 스택에서 더 깊게 호출하면을 직접 사용할 수없는 libcore.io.ForwardingOs.setsockoptInt(...)이고 필요한 파일 설명자는 없습니다. 자바 리플렉션을 사용하면 keepalive 타임 아웃을 설정할 수 있습니다. 어쨌든, e.이 같은 g :이 적어도 작동

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 멤버가 현재 SDK 버전
  • java.net.Socket->impl 현재 SDK 버전
  • java.net.SocketImpl에서 java.net.SocketImpl의 인스턴스는 현재 SDK 버전에서 fd 부재 갖는다
  • TCP_KEEPIDLE, TCP_KEEPINTVLTCP_KEEPCNT 현재 SDK 버전에서 동일한 값 (4, 56)가 모든 안드로이드 장치/아키텍처. 최신 버전5.1.1 r9까지4.0.1/November 2011에서 안드로이드 버전 을 위해 적어도 사실로 보인다

.

platform/libcore 저장소의 luni/src/main/java/libcore/io/Os.java, luni/src/main/java/java/net/Socket.javaluni/src/main/java/java/net/SocketImpl.java을 참조하십시오. TCP_KEEPIDLE, TCP_KEEPINTVLTCP_KEEPCNT2.2.3 r2 및 모든 아키텍처 이후로 안드로이드 버전에 대해 동일한 값을 가진 것으로 보입니다. 예를 들어 유효성을 검사 할 수 있습니다. 저장소 android platform/ndk에서 find . -name tcp.h | xargs grep -ho "TCP_KEEP\w\+\s\+\d\+" | sort | uniq -c을 실행하여

+0

erm ... 내가 추측하는 것만 큼 간단합니다 ... – Bharel

관련 문제