Android: ServerSocket.accept () случайно зависает - PullRequest
0 голосов
/ 20 августа 2011

У меня есть WebView, который подается из фонового потока через ServerSocket на локальном хосте. Это работает очень хорошо, но иногда фоновый поток случайным образом прекращает принимать запросы («Веб-страница недоступна»). Через некоторое время он снова работает без каких-либо изменений, то есть без перезапуска потока или сокета или повторного вызова accept().

РЕДАКТИРОВАТЬ 2: Дальнейшие исследования показали, что WebView, кажется, имеет (отдельное?) Значение тайм-аута для локальных соединений, которое настолько мало, что иногда поток сервера не получает возможности обработать запрос. В качестве обходного пути я могу перезагрузить страницу при вызове WebClient.onReceivedError, что в конечном итоге загружает страницу. У кого-то есть такая же проблема?

Когда я открываю отладчик, я вижу, что серверный поток все еще работает правильно и ожидает (заблокирован) в методе ServerSocket.accept() (или, точнее, в OSNetworkSystem.accept(...)). Однако accept(), похоже, не получает входящий запрос.

В моем коде нет ничего особенного:

ServerSocket serverSocket = new ServerSocket(port);
serverSocket.setSoTimeout(0);

while (!shutdown) {
    Socket socket = null;
    try {
        socket = serverSocket.accept();
        // Parse request and create response
    } catch (Exception e) {
        // ...
    } finally {
        // ... close socket
    }
}

Я использую один и тот же код в Windows / Mac и никогда не сталкивался с такими проблемами.

Это похоже на ошибку в Android, возможно, связанную с оптимизацией управления питанием. Любые подсказки?

РЕДАКТИРОВАТЬ: Проблема не возникает на Android 2.x, только на Android 3.1 (Samsung Galaxy Tab 10.1).

1 Ответ

0 голосов
/ 22 августа 2011

Эта проблема является ошибкой в ​​Android.

Я отправил отчет об ошибке в http://code.google.com/p/android/issues/detail?id=19427

РЕДАКТИРОВАТЬ: В качестве обходного пути я добавил некоторый кодперезагрузите страницу всякий раз, когда происходит ошибка соединения.До сих пор это работало довольно хорошо.

webView.setWebViewClient(new WebViewClient(){
    String prevFailingUrl;
    int retryCount;
    @Override
    public void onReceivedError(WebView view, int errorCode, String description, String failingUrl) {
        if (errorCode == WebViewClient.ERROR_CONNECT) {
            if (failingUrl.equals(prevFailingUrl)) {
                retryCount++;
            } else {
                retryCount = 1;
            }
            if (retryCount <= 3) {
                webView.reload();
            }
        }
        prevFailingUrl = failingUrl;
    }
});
...