2011-08-03 63 views
1

我正在爲Android安裝一個Web服務器,儘管我花了好幾天的時間試圖解決它,但我在這個特定的環境下錯誤。我試圖讀取來自瀏覽器的請求,並且大部分時間代碼都能正常工作,但是有5%的請求失敗,並且拋出隨機SocketTimeoutExceptions,甚至沒有從Socket讀取單個字符。.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試圖從Socket讀取,有時在15後拋出SocketTimeoutException秒數到了。

從日誌語句的輸出在catch在這種情況下是: 插座連接:真實,插座關閉:假的,InputShutDown:假

是怎麼回事?當然,15秒就足以等待了,主流網頁瀏覽器似乎不可能發送任何數據,爲什麼我不能讀取它?

我將不勝感激這個問題的任何輸入。

回答

1

SocketTimeoutException僅意味着一件事:在超時期限內沒有數據可用。所以是的,也許你的超時時間太短了,是的,瀏覽器沒有在超時期限內發送它,或者至少它沒有在超時期限內到達服務器的套接字接收緩衝區。

我會說15秒對於服務器端超時有點積極。 30幾分鐘到幾分鐘會更喜歡它。

+0

謝謝!也許我應該提到完整的代碼實際上將套接字綁定到wifi IP,因此它是一個相對較高的帶寬/低延遲環境。我試着玩更長的超時,但發現我得到的例外數量相同。短暫超時的另一個原因是,我不希望用戶在15秒後發送成功的請求的可能性很小時,不會讓用戶在空白屏幕上盯着兩分鐘。 –

0

我沒有看到任何理由這個代碼會以這種方式失敗,除非像你說的,瀏覽器只是沒有發送任何東西。您可以將ips.read();更改爲System.out.println(ips.read());以確保這一點。如果你看到在stdout上顯示一個字節,那麼瀏覽器確實發送了一些東西。我的猜測是,在您的完整代碼中,您沒有正確識別請求的結束並繼續等待更多數據。 15秒後,你會超時。但這只是一個猜測。如果您發佈了一些能夠證明問題的代碼,有人可能會給出明確的答案。

+0

感謝您的建議。這絕對是第一次讀取失敗,但拋出異常時不讀取單個字節。我開始認爲這是一個特定於設備的問題。我剛剛在不同的設備上運行相同的代碼,無法在超過10k個請求中引發錯誤。將相同的-apk放在摩托羅拉Milestone XT720上,它會爲前50個請求引發5個例外情況。 –

+0

我不確定你會如何檢查那樣的東西。是否有[wireshark](http://www.wireshark.org/)類似於android的工具? –

相關問題