在安卓中出现java.net.SocketTimeoutException: Connection timed out错误

98

我正在开发一个安卓应用,向 Web 服务器发送请求并解析 JSON 对象。经常在与服务器通信时出现 java.net.SocketTimeoutException: Connection timed out 异常。有时它可以完美地工作而没有任何问题。 我知道这个问题已经在 SO 上被问了很多次。但仍然没有得到满意的解决方案。我在下面发布我的日志和应用程序-服务器通信代码。

public JSONObject RequestWithHttpUrlConn(String _url, String param){

    HttpURLConnection con = null;
    URL url;
    String response = "";
    Scanner inStream = null;
    PrintWriter out = null;
    try {
        url = new URL(_url);
        con = (HttpURLConnection) url.openConnection();
        con.setDoOutput(true);
        con.setRequestMethod("POST");
        if(param != null){
            con.setFixedLengthStreamingMode(param.getBytes().length);
        }
        con.setRequestProperty("Content-Type", "application/x-www-form-urlencoded");
        out = new PrintWriter(con.getOutputStream());
        if(param != null){
            out.print(param);
        }
        out.flush();
        out.close();
        inStream = new Scanner(con.getInputStream());

        while(inStream.hasNextLine()){
            response+=(inStream.nextLine());
        }
    } catch (MalformedURLException e) {
        // TODO Auto-generated catch block
        e.printStackTrace();
    } catch (IOException e) {
        // TODO Auto-generated catch block
        e.printStackTrace();
    } finally{
        if(con != null){
            con.disconnect();
        }if(inStream != null){
            inStream.close();
        }if(out != null){
            out.flush();
            out.close();
        }
    }
}

日志记录:

03-25 10:55:32.613: W/System.err(18868): java.net.SocketTimeoutException: Connection 
timed out
03-25 10:55:32.617: W/System.err(18868):at org.apache.harmony.luni.platform.OSNetworkSystem.connect(Native Method)
03-25 10:55:32.617: W/System.err(18868):at dalvik.system.BlockGuard
$WrappedNetworkSystem.connect(BlockGuard.java:357)
03-25 10:55:32.617: W/System.err(18868):at 
org.apache.harmony.luni.net.PlainSocketImpl.connect(PlainSocketImpl.java:204)
03-25 10:55:32.617: W/System.err(18868):at 
org.apache.harmony.luni.net.PlainSocketImpl.connect(PlainSocketImpl.java:437)
03-25 10:55:32.617: W/System.err(18868):at        java.net.Socket.connect(Socket.java:1002)
03-25 10:55:32.621: W/System.err(18868):at 
org.apache.harmony.luni.internal.net.www.protocol.http.HttpConnection.<init>
(HttpConnection.java:75)
03-25 10:55:32.621: W/System.err(18868): at 
org.apache.harmony.luni.internal.net.www.protocol.http.HttpConnection.<init>
(HttpConnection.java:48)03-25 10:55:32.624: W/System.err(18868):at 
org.apache.harmony.luni.internal.net.www.protocol.http.HttpConnection$Address.connect
(HttpConnection.java:322)03-25 10:55:32.624: W/System.err(18868):at 
org.apache.harmony.luni.internal.net.www.protocol.http.HttpConnectionPool.get
(HttpConnectionPool.java:89)03-25 10:55:32.628: W/System.err(18868):at 
org.apache.harmony.luni.internal.net.www.protocol.http.HttpURLConnectionImpl.getHttpCon
nection(HttpURLConnectionImpl.java:285)
03-25 10:55:32.628: W/System.err(18868):at     org.apache.harmony.luni.internal.net.www.protocol.http.HttpURLConnectionImpl.makeConn
ection(HttpURLConnectionImpl.java:267)
03-25 10:55:32.636: W/System.err(18868):at
org.apache.harmony.luni.internal.net.www.protocol.http.HttpURLConnectionImpl.connect
(HttpURLConnectionImpl.java:205)
03-25 10:55:32.636: W/System.err(18868):at 
org.apache.harmony.luni.internal.net.www.protocol.http.HttpURLConnectionImpl.getOutputS
tream(HttpURLConnectionImpl.java:614)
03-25 10:55:32.636: W/System.err(18868):at 
com.myapp.core.JSONRequest.RequestWithHttpUrlConn(JSONRequest.java:63)
03-25 10:55:32.636: W/System.err(18868):    at com.myapp.core.DetailPage
$AsyncRecBooks.doInBackground(AKBookDetailView.java:265)
03-25 10:55:32.640: W/System.err(18868):    at com.myapp.core.DetailPage
$AsyncRecBooks.doInBackground(AKBookDetailView.java:1)
03-25 10:55:32.640: W/System.err(18868):    at android.os.AsyncTask$2.call
(AsyncTask.java:185)
03-25 10:55:32.640: W/System.err(18868):    at java.util.concurrent.FutureTask
$Sync.innerRun(FutureTask.java:306)
03-25 10:55:32.640: W/System.err(18868):    at java.util.concurrent.FutureTask.run
(FutureTask.java:138)
03-25 10:55:32.640: W/System.err(18868):    at 
java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1088)
03-25 10:55:32.648: W/System.err(18868):    at 
java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:581)
03-25 10:55:32.648: W/System.err(18868):    at java.lang.Thread.run(Thread.java:1019)
03-25 10:55:32.652: E/JSON Parser(18868): Error parsing data org.json.JSONException:  
End of input at character 0 of 

这个问题有什么解决方案吗?


1
我认为这是你的网络问题。 - Pragnani
2
我在高速Wi-Fi上测试过了,但这仍然经常发生。 - akh
1
@akh: 确认您使用正确的WebService URL来进行HttpPost请求,或者服务器正在运行。 - ρяσѕρєя K
1
@akh 这不是关于连接速度的问题,而是由于服务器响应的原因。尝试从浏览器窗口调用相同的URL并检查需要多长时间。 - Pragnani
2
@Raghunandan 设置连接超时时间并不能解决连接超时问题。 - user207421
显示剩余5条评论
10个回答

81

我在网上搜索了很多关于连接超时异常的文档,我的理解是,防止 SocketTimeoutException 已经超出了我们的能力范围。 有效处理它的一种方法是定义连接超时,然后使用 try-catch 块进行处理。希望这能帮助未来遇到同样问题的人。

HttpUrlConnection conn = (HttpURLConnection) url.openConnection();

//set the timeout in milliseconds
conn.setConnectTimeout(7000);

47
更改超时时间并不构成“处理”它。捕获异常才算是处理,但你已经在做了。然而,这一切都不能解决问题,因为问题实际上是网络连接问题,根本不是编程问题。 - user207421
6
我同意这是100%的网络问题,而不是编程问题。在“处理”中,我的意思是避免应用程序崩溃。我想要的只是在出现问题时退出应用程序......至于捕获异常,之前我没有捕获SocketTimeoutException......所以我现在会捕获该异常并退出应用程序。 - akh
1
@MuhammadBabar 这意味着在20秒内没有反应,网络出现了一些问题。您需要捕获SocketTimeoutException并适当地处理这种情况。 - akh
1
@EJP 如果增加超时时间不是解决问题的方法,因为正如您所提到的,这是一个网络问题,那么需要采取什么措施来克服这个问题呢? - Salman
1
我正在使用 Retrofit。我设置了 OkHttpClient 并像这样设置:OkHttpClient okHttpClient = new OkHttpClient().newBuilder() .connectTimeout(20, TimeUnit.SECONDS) .readTimeout(20, TimeUnit.SECONDS) .writeTimeout(20, TimeUnit.SECONDS) .build();但是我仍然遇到同样的问题? - Prasad
显示剩余2条评论

33

我知道这个问题有点老了。不过既然我在研究中遇到了这个问题,我想加一点内容可能会有所帮助。

正如所述,客户端无法解决错误,因为它是与网络相关的问题。但是,您可以尝试多次重试连接。这可能作为一种解决方法,直到真正的问题得到解决。

for (int retries = 0; retries < 3; retries++) {
    try {
        final HttpClient client = createHttpClientWithDefaultSocketFactory(null, null);
        final HttpResponse response = client.execute(get);
        final int statusCode = response.getStatusLine().getStatusCode();
        if (statusCode != 200) {
            throw new IllegalStateException("GET Request on '" + get.getURI().toString() + "' resulted in " + statusCode);
        } else {                
            return response.getEntity();
        }
    } catch (final java.net.SocketTimeoutException e) {
        // connection timed out...let's try again                
    }
}

也许这可以帮助某人。


5
如果你正在使用Kotlin + Retrofit + Coroutines,那么在进行网络操作时只需使用try和catch,例如:
viewModelScope.launch(Dispatchers.IO) {
        try {
            val userListResponseModel = apiEndPointsInterface.usersList()
            returnusersList(userListResponseModel)
        } catch (e: Exception) {
            e.printStackTrace()
        }
    }

异常是 kotlin 类型,而不是 java.lang 类型

这将处理所有的异常类型,例如:

  1. HttpException
  2. SocketTimeoutException
  3. FATAL EXCEPTION: DefaultDispatcher等等

这是我的 usersList() 函数

@GET(AppConstants.APIEndPoints.HOME_CONTENT)
suspend fun usersList(): UserListResponseModel

注意:您的RetrofitClient类必须将此作为client

OkHttpClient.Builder()
            .connectTimeout(10, TimeUnit.SECONDS)
            .readTimeout(10, TimeUnit.SECONDS)
            .writeTimeout(10, TimeUnit.SECONDS)

2

如果您正在本地主机上测试服务器,则您的Android设备必须连接到相同的本地网络。然后,您的应用程序使用的服务器URL必须包括您的计算机IP地址,而不是“localhost”掩码。


2

当我连接到 EC2 时,遇到了同样的问题,问题出在安全组上,我通过在端口 5432 添加允许的 IP 地址来解决问题。


0

我遇到了这个问题,解决方法是重新启动我的调制解调器(路由器)。之后,我的应用程序可以连接到互联网。

我认为我正在使用的库没有正确地管理连接,因为这种情况只发生了几次。


0

对我来说,我只是重新启动了我的应用程序,然后问题就解决了。如果您正在使用模拟器,请尝试重新启动它。如果您正在使用物理设备,则请检查网络连接。试试看吧!


-1
在 OkHttpClient.Builder() 对象中设置此项。
val httpClient = OkHttpClient.Builder()
        httpClient.connectTimeout(5, TimeUnit.MINUTES) // connect timeout
            .writeTimeout(5, TimeUnit.MINUTES) // write timeout
            .readTimeout(5, TimeUnit.MINUTES) // read timeout

-2

我遇到了同样的错误,因为我错误地改变了语句的顺序

OkHttpClient okHttpClient = new OkHttpClient().newBuilder() .connectTimeout(20, TimeUnit.SECONDS).readTimeout(20,TimeUnit.SECONDS).writeTimeout(20, TimeUnit.SECONDS) .build();

在更改writeTimeout和readTimeout的顺序后,错误得到了解决。 我使用的最终代码如下:

OkHttpClient okHttpClient = new OkHttpClient.Builder().connectTimeout(60, TimeUnit.SECONDS)
                    .writeTimeout(60, TimeUnit.SECONDS)
                    .readTimeout(60, TimeUnit.SECONDS)
                    .build();

10
改变顺序不应该有影响,因为它所做的只是设置内部字段并构建对象。 - dvallejo

-5
public JSONObject RequestWithHttpUrlConn(String _url, String param){

    HttpURLConnection con = null;
    URL url;
    String response = "";
    Scanner inStream = null;
    PrintWriter out = null;
    try {
        url = new URL(_url);
        con = (HttpURLConnection) url.openConnection();
        con.setDoOutput(true);
        con.setRequestMethod("POST");
        if(param != null){
            con.setFixedLengthStreamingMode(param.getBytes().length);
        }
        con.setRequestProperty("Content-Type", "application/x-www-form-urlencoded");
        out = new PrintWriter(con.getOutputStream());
        if(param != null){
            out.print(param);
        }
        out.flush();
        out.close();
        inStream = new Scanner(con.getInputStream());

        while(inStream.hasNextLine()){
            response+=(inStream.nextLine());
        }
    } catch (MalformedURLException e) {
        // TODO Auto-generated catch block
        e.printStackTrace();
    } catch (IOException e) {
        // TODO Auto-generated catch block
        e.printStackTrace();
    } finally{
        if(con != null){
            con.disconnect();
        }if(inStream != null){
            inStream.close();
        }if(out != null){
            out.flush();
            out.close();
        }
    }
}

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接