The Problem
An app I'm maintaining keeps getting socket timeouts after approximately 21000 ms, despite the fact that I've explicitly set longer timeouts. This seemingly magical value of 21000 ms has come up in a few other SO questions and answers, and I'm trying to figure out exactly where it comes from.
Here's the essence of my code:
HttpURLConnection connection = null;
try {
URL url = new URL(urlString);
connection = (HttpURLConnection) url.openConnection();
connection.setConnectTimeout(45000);
connection.setReadTimeout(90000);
int responseCode = connection.getResponseCode();
if (responseCode == 200) {
// code omitted
}
} catch (Exception e) {
// code omitted
}
finally {
if (connection != null) {
connection.disconnect();
}
}
Catching all exceptions in one block is admittedly not ideal, but it's inherited code and I'm reluctant to mess with it. I know it's catching SocketTimeoutException
after 21000 ms because it logs the simple name of the exception class.
Clues
I found a question where an asker was getting a ConnectTimeout
after 21000 ms, despite explicitly setting it to 40000 ms. That's intriguing despite the exception class being different.
I also found a poorly-explained answer which claims that the server side is responsible for the 21000 ms timeout.
My Hunch
I don't think any action or inaction of the server could cause a shorter-than-expected socket timeout on the client. But maybe the TCP stacks in Windows and Android share a common ancestor, or at least use similar connect retry logic.
Could it be that Android imposes a maximum connect timeout of 21000 ms, and setting a longer timeout in HttpURLConnection
is futile? Or could this timeout be triggered by some Windows machine on the path between the mobile device and the server? Do some Android versions throw a SocketTimeoutException
where others throw a ConnectException
?
See Question&Answers more detail:
os 与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…