android - 来自 Android 的大量 HTTP 请求导致网络断开。如何解决这个问题?

标签 android apache apache-httpclient-4.x android-networking androidhttpclient

我的 android 开发现在遇到了一个非常烦人的问题。我有一个加载一堆内容的列表,每个都是一个具有不同地址的 xml 文件。这意味着我需要向服务器发送一堆 http get 请求。

如果请求少于大约 180 次就会出现问题,我的意思是继续,非常快的 http 请求,应用程序运行良好。当数量达到 180 左右时,整个设备将失去与互联网的连接。这意味着不仅该应用程序无法运行,甚至默认浏览器或其他需要互联网的应用程序也将无法运行。

这将在一两分钟后恢复。但在此期间没有互联网连接。

我确实在 mifest 文件中设置了权限。

这是我的 http 连接代码:

public class HTTPService {


    private static String response;


    public  HTTPService() {
        response = null;
    }


    public static String httpGet(String requestURL) {

        //Reset response's value to null
        response = null;
        //DEBUG LOG
        Log.i("HTTPService", "Start GET request with URL " + requestURL);

        //this function will do http getting action and response checking at same time.
        //and assign proper information into the response string.
        executeRequest(new HttpGet(requestURL));

        Log.i("HTTPService", "GET request return with: " + response);

        return response;
    }

    public static String httpPost(String requestURL, String postString) throws Exception {

        //Assemble POST request
        HttpPost request = new HttpPost(requestURL);
        StringEntity input = new StringEntity(postString);
        input.setContentType(CommonCodes.CONTENT_TYPE);
        request.setEntity(input);

        //DEBUG LOG
        Log.i("HTTPService", "Start POST request with URL" + requestURL + ", and post content " + postString);

        executeRequest(request);

        return response;

    }

    public static void httpPut(String requestURL, String postString) throws Exception {

        //Assemble PUT request
        HttpPut request = new HttpPut(requestURL);
        StringEntity input = new StringEntity(postString);
        input.setContentType(CommonCodes.CONTENT_TYPE);
        request.setEntity(input);

        //DEBUG LOG
        Log.i("HTTPService", "Start PUT request with URL" + requestURL + ", and put content " + postString);

        executeRequest(request);

    }

    public static String httpDelete(String requestURL) {

        HttpDelete request = new HttpDelete(requestURL);
        //DEBUG LOG
        Log.i("HTTPService", "Start DELETE request with URL" + requestURL);
        executeRequest(request);
        return response;

    }


    public static void executeRequest(HttpUriRequest request) {

        //Check Internet Connection
        if (!CheckInternetConnection.checkInternetConnection()) {
            responseValidation(CommonCodes.NO_CONNECTION, 0);
        }




        HttpClient client = sslHttpClient();
        HttpResponse httpResponse;

        try {


            //*********PLACE WHERE ERROR HAPPENS IN ERROR LOG!******//
            httpResponse = client.execute(request);

            //Check if the request success. If it success, should return 200 as status code.
            if (httpResponse.getStatusLine().getStatusCode() != CommonCodes.HTTP_SUCCESS) {
                //DEBUG LOG
                Log.i("HTTPService", "Request failed with HTTP status code" + httpResponse.getStatusLine().getStatusCode());
                //Go through checker
                responseValidation(null, httpResponse.getStatusLine().getStatusCode());
            }

            //When request succeed, retrieve data.
            //HttpEntity entity = httpResponse.getEntity();

            //Convert stream data into String.
            if (!httpResponse.getEntity().equals(null)) {

                InputStream instream = httpResponse.getEntity().getContent();

                //Convert InputStream to String.
                response = convertStreamToString(instream).trim();

                //Close stream
                instream.close();
                httpResponse.getEntity().consumeContent();
            }

            //Go through checker
            responseValidation(response, httpResponse.getStatusLine().getStatusCode());

            client.getConnectionManager().shutdown();

        } catch (ClientProtocolException e) {
            Log.e("HTTPService: ", "HTTP Request With ClientProtocolException Detected");
            client.getConnectionManager().shutdown();
            e.printStackTrace();

        } catch (IOException e) {
            Log.e("HTTPService: ", "HTTP Request With IOException Detected");
            client.getConnectionManager().shutdown();
            e.printStackTrace();

        }

    }



    public static void  responseValidation (String response, int statusCode)
    {
        //Is this a HTTP Error?
        if (statusCode != CommonCodes.HTTP_SUCCESS) {
            response = CommonCodes.HTTP_FAIL;
        }
        //Is the response contains nothing?
        else if (response.equals(null) || response.equals("")) {
            response = CommonCodes.RESPONSE_EMPTY;
        }
        //Is there an internet connection?
        else if (response.equals(CommonCodes.NO_CONNECTION)){
            response = CommonCodes.NO_CONNECTION;
        }

    }


    public static HttpClient sslHttpClient() {
        try {
            KeyStore trustStore = KeyStore.getInstance(KeyStore.getDefaultType());
            trustStore.load(null, null);

            SSLSocketFactory sf = new SSLSocket(trustStore);
            sf.setHostnameVerifier(SSLSocketFactory.ALLOW_ALL_HOSTNAME_VERIFIER);

            HttpParams params = new BasicHttpParams();
            HttpProtocolParams.setVersion(params, HttpVersion.HTTP_1_1);
            HttpProtocolParams.setContentCharset(params, HTTP.UTF_8);

            SchemeRegistry registry = new SchemeRegistry();
            registry.register(new Scheme("http", PlainSocketFactory
                    .getSocketFactory(), 8080));
            registry.register(new Scheme("https", sf, 8443));


            ClientConnectionManager ccm = new ThreadSafeClientConnManager(
                    params, registry);


            return new DefaultHttpClient(ccm, params);
        } catch (Exception e) {
            return new DefaultHttpClient();
        }
    }

    private static String convertStreamToString(InputStream is) {
        BufferedReader reader = new BufferedReader(new InputStreamReader(is));
        StringBuilder sb = new StringBuilder();

        String line = null;
        try {
            while ((line = reader.readLine()) != null) {
                sb.append(line + "\n");
            }
        } catch (IOException e) {
            e.printStackTrace();
        } finally {
            try {
                is.close();
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
        return sb.toString();
    }

连接丢失时我得到的错误信息是这样的:

05-06 12:13:57.697  28670-28767/com.lai.android E/HTTPService:﹕ HTTP Request With IOException Detected
05-06 12:13:57.697  28670-28767/com.lai.android W/System.err﹕ org.apache.http.conn.HttpHostConnectException: Connection to http://test.myworkspace.com:8080 refused
05-06 12:13:57.697  28670-28767/com.lai.android W/System.err﹕ at org.apache.http.impl.conn.DefaultClientConnectionOperator.openConnection(DefaultClientConnectionOperator.java:183)
05-06 12:13:57.697  28670-28767/com.lai.android W/System.err﹕ at org.apache.http.impl.conn.AbstractPoolEntry.open(AbstractPoolEntry.java:164)
05-06 12:13:57.697  28670-28767/com.lai.android W/System.err﹕ at org.apache.http.impl.conn.AbstractPooledConnAdapter.open(AbstractPooledConnAdapter.java:119)
05-06 12:13:57.697  28670-28767/com.lai.android W/System.err﹕ at org.apache.http.impl.client.DefaultRequestDirector.execute(DefaultRequestDirector.java:360)
05-06 12:13:57.697  28670-28767/com.lai.android W/System.err﹕ at org.apache.http.impl.client.AbstractHttpClient.execute(AbstractHttpClient.java:555)
05-06 12:13:57.697  28670-28767/com.lai.android W/System.err﹕ at org.apache.http.impl.client.AbstractHttpClient.execute(AbstractHttpClient.java:487)
05-06 12:13:57.697  28670-28767/com.lai.android W/System.err﹕ at org.apache.http.impl.client.AbstractHttpClient.execute(AbstractHttpClient.java:465)
05-06 12:13:57.697  28670-28767/com.lai.android W/System.err﹕ at com.lai.android.services.http.HTTPService.executeRequest(HTTPService.java:138)
05-06 12:13:57.697  28670-28767/com.lai.android W/System.err﹕ at com.lai.android.services.http.HTTPService.httpGet(HTTPService.java:73)
05-06 12:13:57.697  28670-28767/com.lai.android W/System.err﹕ at com.lai.android.modules.watchlistgroup.WatchListActivity.getSingleVehicle(WatchListActivity.java:238)
05-06 12:13:57.697  28670-28767/com.lai.android W/System.err﹕ at com.lai.android.modules.watchlistgroup.WatchListActivity$InitWatchListActivity.doInBackground(WatchListActivity.java:144)
05-06 12:13:57.705  28670-28767/com.lai.android W/System.err﹕ at com.lai.android.modules.watchlistgroup.WatchListActivity$InitWatchListActivity.doInBackground(WatchListActivity.java:109)
05-06 12:13:57.705  28670-28767/com.lai.android W/System.err﹕ at android.os.AsyncTask$2.call(AsyncTask.java:287)
05-06 12:13:57.705  28670-28767/com.lai.android W/System.err﹕ at java.util.concurrent.FutureTask$Sync.innerRun(FutureTask.java:305)
05-06 12:13:57.705  28670-28767/com.lai.android W/System.err﹕ at java.util.concurrent.FutureTask.run(FutureTask.java:137)
05-06 12:13:57.705  28670-28767/com.lai.android W/System.err﹕ at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1076)
05-06 12:13:57.705  28670-28767/com.lai.android W/System.err﹕ at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:569)
05-06 12:13:57.705  28670-28767/com.lai.android W/System.err﹕ at java.lang.Thread.run(Thread.java:856)
05-06 12:13:57.705  28670-28767/com.lai.android W/System.err﹕ Caused by: java.net.ConnectException: failed to connect to /192.168.48.95 (port 8080): connect failed: ENETUNREACH (Network is unreachable)
05-06 12:13:57.705  28670-28767/com.lai.android W/System.err﹕ at libcore.io.IoBridge.connect(IoBridge.java:114)
05-06 12:13:57.713  28670-28767/com.lai.android W/System.err﹕ at java.net.PlainSocketImpl.connect(PlainSocketImpl.java:192)
05-06 12:13:57.713  28670-28767/com.lai.android W/System.err﹕ at java.net.PlainSocketImpl.connect(PlainSocketImpl.java:459)
05-06 12:13:57.713  28670-28767/com.lai.android W/System.err﹕ at java.net.Socket.connect(Socket.java:842)
05-06 12:13:57.713  28670-28767/com.lai.android W/System.err﹕ at org.apache.http.conn.scheme.PlainSocketFactory.connectSocket(PlainSocketFactory.java:119)
05-06 12:13:57.713  28670-28767/com.lai.android W/System.err﹕ at org.apache.http.impl.conn.DefaultClientConnectionOperator.openConnection(DefaultClientConnectionOperator.java:144)
05-06 12:13:57.713  28670-28767/com.lai.android W/System.err﹕ ... 17 more
05-06 12:13:57.713  28670-28767/com.lai.android W/System.err﹕ Caused by: libcore.io.ErrnoException: connect failed: ENETUNREACH (Network is unreachable)
05-06 12:13:57.713  28670-28767/com.lai.android W/System.err﹕ at libcore.io.Posix.connect(Native Method)
05-06 12:13:57.713  28670-28767/com.lai.android W/System.err﹕ at libcore.io.BlockGuardOs.connect(BlockGuardOs.java:85)
05-06 12:13:57.713  28670-28767/com.lai.android W/System.err﹕ at libcore.io.IoBridge.connectErrno(IoBridge.java:127)
05-06 12:13:57.713  28670-28767/com.lai.android W/System.err﹕ at libcore.io.IoBridge.connect(IoBridge.java:112)
05-06 12:13:57.721  28670-28767/com.lai.android W/System.err﹕ ... 22 more

欢迎任何建议!我在想这是否是由端口运行引起的。但我不知道如何解决。谢谢!

最佳答案

幸运的....我解决了它。

问题是我有太多的 HTTP 客户端实例,用完了手机上的所有端口。

Android 有最大连接数限制,释放已使用的端口需要时间。因此,如果请求很重并且在很短的时间内发生,设备将没有足够的时间来释放它们。

解决方案不是每次都使用新客户端,而是对所有请求只使用一个客户端。

将此添加到代码中:

private static HttpClient client;


public static synchronized void createHttpClient() {
    if(client == null) {
        Log.i("HTTPService", "Create Client");
        client = sslHttpClient();
    }

}

然后从应用程序的开头调用此构造函数。

然后用静态客户端替换所有创建新的 http 客户端的地方。

问题解决了,我去喝杯啤酒。

关于android - 来自 Android 的大量 HTTP 请求导致网络断开。如何解决这个问题?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/23501232/

相关文章:

php - Laravel Composer错误未捕获的ReflectionException:Container.php:738中不存在类日志

java - HttpClient URL 调用失败

android - 未知的 ListView 行为

android - 与 Android 设置向导交互

java - 获取将从 HttpPost 发送的完整的原始 HTTP 请求消息

java - org.apache.tiles.definition.NoSuchDefinitionException

java - 如何诊断泄漏的 http 连接 (org.apache.http.impl.conn.tsccm.ConnPoolByRoute)

java - apache httpclient 内容长度问题

java - android,如何获取目录列表?

android - 如何通过点击下载文件