Android: ServerSocket.accept() randomly freezes
I have a WebView
that is fed from a background thread via a ServerSocket
on localhost. This works very well, but sometimes the background thread randomly stops accepting requests ("Web page not available"). After some time, it works again without any changes, th开发者_JS百科at is, without restarting the thread or the socket or calling accept()
again.
EDIT 2: Further investigation showed that WebView
seems to have a (separate?) timeout value for localhost connections that is so small that sometimes the server thread doesn't get a chance to handle the request. As a workaround, I can reload the page when WebClient.onReceivedError
is invoked, which eventually loads the page. Anyone having the same problem?
When I open the debugger, I can see that the server thread is still running properly and is waiting (blocked) in the ServerSocket.accept()
method (or, more precisely, in OSNetworkSystem.accept(...)
). However, accept()
doesn't seem to receive the incoming request.
There is is nothing special in my code:
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
}
}
I use the same code on Windows/Mac and have never experienced any such problems.
This seems to me like a bug in Android, perhaps related to power management optimizations. Any clues?
EDIT: The problem does not occur on Android 2.x, only on Android 3.1 (Samsung Galaxy Tab 10.1).
This problem is a bug in Android.
I have filed a bug report under http://code.google.com/p/android/issues/detail?id=19427
EDIT: As a workaround, I added some code to reload the page whenever a connection error occurs. This has worked quite well so far.
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;
}
});
精彩评论