21000毫秒的套接字超时从何而来? [英] Where does the socket timeout of 21000 ms come from?

查看:65
本文介绍了21000毫秒的套接字超时从何而来?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

问题

尽管我明确设置了更长的超时时间,但我正在维护的一个应用在大约21000 ms之后仍会出现套接字超时.这个看似神奇的21000 ms的价值已经出现在其他一些SO问题和答案中,我正试图找出它的确切来源.

这是我的代码的本质:

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();
    }
}

在一个块中捕获所有异常虽然不是很理想,但是它是继承的代码,我不愿意将其弄乱.我知道它在21000 ms之后捕获了SocketTimeoutException,因为它记录了异常类的简单名称.

线索

我发现一个问题,询问者在21000毫秒后得到 ConnectTimeout ,尽管将其显式设置为40000 ms.尽管异常类有所不同,这还是很有趣的.

我还找到了一个难以解释的答案,该答案声称服务器端是21000 ms超时的原因./p>

我的午餐

我认为服务器的任何动作或不动作都不会导致客户端上的套接字超时短于预期.但是也许Windows和Android中的TCP堆栈共享一个共同的祖先,或者至少使用类似的连接重试逻辑.

是否可能是Android施加21000 ms的最大连接超时,并且在HttpURLConnection中设置更长的超时是徒劳的?还是由移动设备和服务器之间路径上的某些Windows计算机触发此超时?某些Android版本是否抛出SocketTimeoutException而其他版本抛出ConnectException?

解决方案

我根据问题中的代码编写了一个粗略的测试应用,该应用尝试通过尝试连接到不可路由的地址来模拟连接超时,如此答案.在我的Moto G(Android 4.4.2)上,它按预期在大约45秒内抛出了SocketTimeoutException.奇怪的是,如果我没有明确设置连接超时,它会在大约一分钟后抛出ConnectException.

我将编写一个稍微复杂一些的测试应用程序,然后将其发送给客户,以尝试确定设备本身是否设置了21秒超时,或者其移动网络上的某些路由器是否可能是罪魁祸首.我将用结果更新此答案.

结果:这似乎是一个操作系统错误,影响了Sprint的Samsung SPH-P100(Galaxy Tab 1).我无法从任何其他运营商访问Tab 1.这可能归咎于三星或Sprint.它似乎一般不会影响Android 2.x,因为我的ZTE X501运行2.3.6,可以设置更长的超时时间.

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?

解决方案

I wrote a crude test app, based on the code in my question, that simulates a connect timeout by attempting to connect to a non-routable address as suggested in this answer. On my Moto G (Android 4.4.2), it throws a SocketTimeoutException in approximately 45 seconds as expected. Curiously, if I do not explicitly set the connect timeout, it instead throws a ConnectException after approximately one minute.

I'm going to write a slightly more sophisticated test app and send it to the customer to try to determine if the device itself is imposing a 21s timeout, or if some router on their mobile network might be the culprit. I'll update this answer with the results.

Result: This appears to be an OS bug that affects the Samsung SPH-P100 (Galaxy Tab 1) from Sprint. I don't have access to a Tab 1 from any other carrier, so this could be blamed on Samsung or Sprint. It does not seem to generally affect Android 2.x, because I have a ZTE X501 running 2.3.6 which allows me to set longer timeouts.

这篇关于21000毫秒的套接字超时从何而来?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆