2011-08-03 3 views
1

나는 안드로이드 용 웹 서버에서 일하고 있습니다. 고칠 시간을 보냈지 만,이 특별한 곤충. 브라우저에서 요청을 읽으려고하는데 대부분의 경우 코드가 제대로 작동하지만 요청의 5 %가 실패하고 Socket의 단일 문자를 읽지 않아도 임의의 SocketTimeoutExceptions가 throw됩니다..read()는 데이터가 있어야하더라도 간헐적 인 SocketTimeoutException을 던졌습니다.

다른 브라우저에서이를 테스트했으며 모든 브라우저에서이 문제가 발생했습니다. 따라서 문제가 있습니다.

public class ServerThread extends Thread { 

private ServerSocket ss = null; 
private boolean isRunning; 

private ExecutorService threadPool = new ThreadPoolExecutor(2, 12, 
      60L, TimeUnit.SECONDS, 
      new SynchronousQueue<Runnable>(), 
      Executors.defaultThreadFactory(), 
      new ThreadPoolExecutor.CallerRunsPolicy()); 

public ServerThread() { 
} 

public synchronized void run() { 
    ss = new ServerSocket(8080, 1); 
    isRunning = true; 

    while (isRunning) { 
     Socket clientSocket = null; 

     try { 
      if (ss != null) { 
       clientSocket = ss.accept(); 
       if (isRunning) { 
        this.threadPool.execute(new HTTPSession(clientSocket)); 
       } 
      } 
     } catch (IOException e) { 
      e.printStackTrace(); 
     } 
    } 
} 
} 

: 그리고 여기에 가능한 한 멀리 벗었 관련 코드의

public class HTTPSession implements Runnable { 

private Socket mSocket = null; 

public HTTPSession (Socket s) { 
    mSocket = s; 
} 


public void run() { 

    InputStream ips = null; 

    try { 
     mSocket.setSoTimeout(15000); 
     ips = mSocket.getInputStream(); 
     ips.read(); 
    } 
    catch (Exception e) { 
     e.printStackTrace(); 
     Log.v("HTTPSession", "Socket connected: " + mSocket.isConnected() + ", Socket closed: " + mSocket.isClosed() + ", InputShutdown: " + mSocket.isInputShutdown()); 
    } 
    finally { 
      try { ips.close(); } catch (IOException ioe) { } 
      try { mSocket.close(); } catch (IOException ioe) { } 
    } 

} 
} 

그래서있는 ServerThread가 연결을 받아들이는 HTTPSession에 소켓에서 읽기를 시도하고 때때로 15 후에 지정해 SocketTimeoutException를 던졌습니다 초 있습니다.

이 경우 캐치에 로그인 문의 출력은 다음과 같습니다 소켓 연결 : 사실, 소켓 폐쇄 : 거짓, InputShutDown :

무엇 제공

거짓을? 물론 15 초만으로도 충분하며 주류 웹 브라우저가 데이터를 전송하지 않을 것 같아서 왜 읽을 수 없습니까?

이 문제에 대한 의견을 보내 주시면 감사하겠습니다.

답변

1

SocketTimeoutException은 한 가지만 의미합니다. 시간 초과 기간 내에 데이터를 사용할 수 없었습니다. 그래서 네 타임 아웃이 너무 짧다. 예, 브라우저가 타임 아웃 기간 내에 그것을 보내지 않았거나 적어도 타임 아웃 기간 내에 서버의 소켓 수신 버퍼에 도착하지 않았다.

15 초가 서버 쪽 시간 초과에 대해 다소 공격적이라고 말합니다. 30 분에서 2 분 정도면 더 좋아질 것입니다.

+0

감사! 아마도 전체 코드가 실제로 소켓을 Wi-Fi IP에 바인딩한다고 언급 했어야했기 때문에 비교적 높은 대역폭/낮은 대기 시간 환경이었습니다. 더 긴 타임 아웃으로 놀아 보려고했지만 같은 수의 예외가 있다는 것을 알았습니다. 짧은 시간 제한의 또 다른 이유는 사용자가 빈 화면을 2 분 동안 쳐다 보지 않고 15 초 후에 성공적인 요청이 전송되는 것을 원하지 않는다는 것입니다. –

0

내가 말한 것처럼 브라우저가 아무 것도 보내지 않으면이 코드가 실패하는 이유가 없습니다. ips.read();System.out.println(ips.read());으로 변경할 수 있습니다. stdout에 바이트가 표시되면 브라우저가 무언가를 보냈습니다. 내 생각 엔 전체 코드에서 요청의 끝을 제대로 인식하지 못하고 더 많은 데이터를 기다리는 것입니다. 15 초 후에 시간이 초과됩니다. 그러나 그것은 단지 추측입니다. 문제를 나타내는 코드를 게시하면 누군가가 당신에게 확실한 답을 줄 수 있습니다.

+0

제안 해 주셔서 감사합니다. 그것은 예외가 던져 질 때 싱글 바이트를 읽지 않고 실패한 첫 번째 읽기입니다. 나는 이것이 장치 특정 문제라고 생각하기 시작했습니다. 나는 지금 다른 장치에서 같은 코드를 실행했고 10k 개 이상의 요청에서 오류를 유발할 수 없었습니다. Motorola Milestone XT720에 동일한 -apk를 넣으면 처음 50 건의 요청에 대해 5 가지 예외가 발생합니다. –

+0

나는 어떻게 그런 식으로 체크 할 것인지는 잘 모르겠습니다. android 용 [wireshark] (http://www.wireshark.org/)와 같은 유틸리티가 있습니까? –

관련 문제