Cách đặt thời gian chờ httpResponse cho Android bằng Java


333

Tôi đã tạo chức năng sau để kiểm tra trạng thái kết nối:

private void checkConnectionStatus() {
    HttpClient httpClient = new DefaultHttpClient();

    try {
      String url = "http://xxx.xxx.xxx.xxx:8000/GaitLink/"
                   + strSessionString + "/ConnectionStatus";
      Log.d("phobos", "performing get " + url);
      HttpGet method = new HttpGet(new URI(url));
      HttpResponse response = httpClient.execute(method);

      if (response != null) {
        String result = getResponse(response.getEntity());
        ...

Khi tôi tắt máy chủ để kiểm tra, việc thực thi sẽ đợi rất lâu

HttpResponse response = httpClient.execute(method);

Có ai biết cách đặt thời gian chờ để tránh chờ đợi quá lâu không?

Cảm ơn!

Câu trả lời:


625

Trong ví dụ của tôi, hai thời gian chờ được đặt. Thời gian chờ kết nối ném java.net.SocketTimeoutException: Socket is not connectedvà thời gian chờ ổ cắm java.net.SocketTimeoutException: The operation timed out.

HttpGet httpGet = new HttpGet(url);
HttpParams httpParameters = new BasicHttpParams();
// Set the timeout in milliseconds until a connection is established.
// The default value is zero, that means the timeout is not used. 
int timeoutConnection = 3000;
HttpConnectionParams.setConnectionTimeout(httpParameters, timeoutConnection);
// Set the default socket timeout (SO_TIMEOUT) 
// in milliseconds which is the timeout for waiting for data.
int timeoutSocket = 5000;
HttpConnectionParams.setSoTimeout(httpParameters, timeoutSocket);

DefaultHttpClient httpClient = new DefaultHttpClient(httpParameters);
HttpResponse response = httpClient.execute(httpGet);

Nếu bạn muốn đặt Tham số của bất kỳ HTTPClient nào (ví dụ: DefaultHttpClient hoặc AndroidHttpClient), bạn có thể sử dụng hàm setParams () .

httpClient.setParams(httpParameters);

1
@Thomas: Tôi đã chỉnh sửa câu trả lời của mình bằng một giải pháp cho usecase của bạn
kuester2000

3
HttpResponse sẽ trả về cái gì nếu hết thời gian kết nối? Hiện tại, khi yêu cầu HTTP của tôi được thực hiện, tôi sẽ kiểm tra mã trạng thái khi cuộc gọi trở lại, tuy nhiên tôi nhận được NullPulumException khi kiểm tra mã này nếu cuộc gọi đã hết thời gian ... về cơ bản, làm thế nào để tôi xử lý tình huống khi cuộc gọi hết thời gian? (Tôi đang sử dụng mã rất giống với câu trả lời của bạn đã đưa ra)
Tim

10
@jellyfish - Mặc dù có tài liệu hướng dẫn, AndroidHttpClient không mở rộng DefaultHttpClient; đúng hơn, nó thực hiện HTTPClient. Bạn sẽ cần sử dụng DefaultHttpClient để có sẵn phương thức setParams (HttpParams).
Ted Hopp

3
Hey guys, t hanks cho câu trả lời tuyệt vời. Nhưng, tôi muốn hiển thị bánh mì nướng cho người dùng khi hết thời gian kết nối ... có cách nào tôi có thể phát hiện khi hết kết nối không?
Arnab Chakraborty

2
Không hoạt động. Tôi đã thử nghiệm trên Sony và Moto của mình, tất cả chúng đều được giấu kín.
thecr0w

13

Để đặt cài đặt trên máy khách:

AndroidHttpClient client = AndroidHttpClient.newInstance("Awesome User Agent V/1.0");
HttpConnectionParams.setConnectionTimeout(client.getParams(), 3000);
HttpConnectionParams.setSoTimeout(client.getParams(), 5000);

Tôi đã sử dụng thành công trên JellyBean, nhưng cũng nên hoạt động cho các nền tảng cũ hơn ....

HTH


mối quan hệ với httpClient là gì?
Sazzad Hissain Khan

8

Nếu bạn đang sử dụng thư viện máy khách http của Jakarta thì bạn có thể làm một cái gì đó như:

        HttpClient client = new HttpClient();
        client.getParams().setParameter(HttpClientParams.CONNECTION_MANAGER_TIMEOUT, new Long(5000));
        client.getParams().setParameter(HttpClientParams.SO_TIMEOUT, new Integer(5000));
        GetMethod method = new GetMethod("http://www.yoururl.com");
        method.getParams().setParameter(HttpMethodParams.SO_TIMEOUT, new Integer(5000));
        method.getParams().setParameter(HttpMethodParams.RETRY_HANDLER,
        int statuscode = client.executeMethod(method);

5
HttpClientParams.CONNMENT_MANAGER_TIME hiện không xác định
Tawani

Bạn nên sử dụng client.getParams (). SetIntParameter (..) cho các thông số * _TIMEOUT
loafoe

Làm thế nào để tìm? Thiết bị được kết nối với wifi nhưng không thực sự hoạt động dữ liệu thông qua wifi.
Ganesh Katikar


5

Đối với những người nói rằng câu trả lời của @ kuester2000 không hoạt động, xin lưu ý rằng các yêu cầu HTTP, trước tiên hãy thử tìm IP máy chủ với yêu cầu DNS và sau đó thực hiện yêu cầu HTTP thực tế đến máy chủ, vì vậy bạn cũng có thể cần phải đặt thời gian chờ cho yêu cầu DNS.

Nếu mã của bạn hoạt động mà không có thời gian chờ cho yêu cầu DNS thì đó là vì bạn có thể truy cập máy chủ DNS hoặc bạn đang nhấn bộ đệm DNS của Android. Bằng cách này, bạn có thể xóa bộ nhớ cache này bằng cách khởi động lại thiết bị.

Mã này mở rộng câu trả lời ban đầu để bao gồm tra cứu DNS thủ công với thời gian chờ tùy chỉnh:

//Our objective
String sURL = "http://www.google.com/";
int DNSTimeout = 1000;
int HTTPTimeout = 2000;

//Get the IP of the Host
URL url= null;
try {
     url = ResolveHostIP(sURL,DNSTimeout);
} catch (MalformedURLException e) {
    Log.d("INFO",e.getMessage());
}

if(url==null){
    //the DNS lookup timed out or failed.
}

//Build the request parameters
HttpParams params = new BasicHttpParams();
HttpConnectionParams.setConnectionTimeout(params, HTTPTimeout);
HttpConnectionParams.setSoTimeout(params, HTTPTimeout);

DefaultHttpClient client = new DefaultHttpClient(params);

HttpResponse httpResponse;
String text;
try {
    //Execute the request (here it blocks the execution until finished or a timeout)
    httpResponse = client.execute(new HttpGet(url.toString()));
} catch (IOException e) {
    //If you hit this probably the connection timed out
    Log.d("INFO",e.getMessage());
}

//If you get here everything went OK so check response code, body or whatever

Phương pháp sử dụng:

//Run the DNS lookup manually to be able to time it out.
public static URL ResolveHostIP (String sURL, int timeout) throws MalformedURLException {
    URL url= new URL(sURL);
    //Resolve the host IP on a new thread
    DNSResolver dnsRes = new DNSResolver(url.getHost());
    Thread t = new Thread(dnsRes);
    t.start();
    //Join the thread for some time
    try {
        t.join(timeout);
    } catch (InterruptedException e) {
        Log.d("DEBUG", "DNS lookup interrupted");
        return null;
    }

    //get the IP of the host
    InetAddress inetAddr = dnsRes.get();
    if(inetAddr==null) {
        Log.d("DEBUG", "DNS timed out.");
        return null;
    }

    //rebuild the URL with the IP and return it
    Log.d("DEBUG", "DNS solved.");
    return new URL(url.getProtocol(),inetAddr.getHostAddress(),url.getPort(),url.getFile());
}   

Lớp học này là từ bài viết trên blog này . Đi và kiểm tra các nhận xét nếu bạn sẽ sử dụng nó.

public static class DNSResolver implements Runnable {
    private String domain;
    private InetAddress inetAddr;

    public DNSResolver(String domain) {
        this.domain = domain;
    }

    public void run() {
        try {
            InetAddress addr = InetAddress.getByName(domain);
            set(addr);
        } catch (UnknownHostException e) {
        }
    }

    public synchronized void set(InetAddress inetAddr) {
        this.inetAddr = inetAddr;
    }
    public synchronized InetAddress get() {
        return inetAddr;
    }
}

1
HttpParams httpParameters = new BasicHttpParams();
            HttpProtocolParams.setVersion(httpParameters, HttpVersion.HTTP_1_1);
            HttpProtocolParams.setContentCharset(httpParameters,
                    HTTP.DEFAULT_CONTENT_CHARSET);
            HttpProtocolParams.setUseExpectContinue(httpParameters, true);

            // Set the timeout in milliseconds until a connection is
            // established.
            // The default value is zero, that means the timeout is not used.
            int timeoutConnection = 35 * 1000;
            HttpConnectionParams.setConnectionTimeout(httpParameters,
                    timeoutConnection);
            // Set the default socket timeout (SO_TIMEOUT)
            // in milliseconds which is the timeout for waiting for data.
            int timeoutSocket = 30 * 1000;
            HttpConnectionParams.setSoTimeout(httpParameters, timeoutSocket);

Không hoàn thành. Có liên quan gì với httpClient?
Sazzad Hissain Khan

1

bạn có thể tạo cá thể HTTPClient bằng cách sử dụng httpclient-android-4.3.5, nó có thể hoạt động tốt.

 SSLContext sslContext = SSLContexts.createSystemDefault();
        SSLConnectionSocketFactory sslsf = new SSLConnectionSocketFactory(
                sslContext,
                SSLConnectionSocketFactory.STRICT_HOSTNAME_VERIFIER);
                RequestConfig.Builder requestConfigBuilder = RequestConfig.custom().setCircularRedirectsAllowed(false).setConnectionRequestTimeout(30*1000).setConnectTimeout(30 * 1000).setMaxRedirects(10).setSocketTimeout(60 * 1000);
        CloseableHttpClient hc = HttpClients.custom().setSSLSocketFactory(sslsf).setDefaultRequestConfig(requestConfigBuilder.build()).build();

1

Một tùy chọn là sử dụng ứng dụng khách OkHttp , từ Square.

Thêm phụ thuộc thư viện

Trong build.gradle, bao gồm dòng này:

compile 'com.squareup.okhttp:okhttp:x.x.x'

Trong trường hợp x.x.xlà phiên bản thư viện mong muốn.

Đặt máy khách

Ví dụ: nếu bạn muốn đặt thời gian chờ là 60 giây, hãy thực hiện theo cách này:

final OkHttpClient okHttpClient = new OkHttpClient();
okHttpClient.setReadTimeout(60, TimeUnit.SECONDS);
okHttpClient.setConnectTimeout(60, TimeUnit.SECONDS);

ps: Nếu minSdkVersion của bạn lớn hơn 8, bạn có thể sử dụng TimeUnit.MINUTES. Vì vậy, bạn chỉ cần sử dụng:

okHttpClient.setReadTimeout(1, TimeUnit.MINUTES);
okHttpClient.setConnectTimeout(1, TimeUnit.MINUTES);

Để biết thêm chi tiết về các đơn vị, xem TimeUnit .


Trong phiên bản hiện tại của OkHttp, thời gian chờ cần phải được đặt khác nhau: https://github.com/sapes/okhttp/blob/master/samples/guide/src/main/java/okhttp3/recipes/ConfigureTimeouts.java
thijsonline

1

Nếu bạn đang sử dụng HttpURLConnection, hãy gọi setConnectTimeout()như được mô tả ở đây :

URL url = new URL(myurl);
HttpURLConnection conn = (HttpURLConnection) url.openConnection();
conn.setConnectTimeout(CONNECT_TIMEOUT);

Mô tả giống như thời gian chờ để thiết lập kết nối, thay vì yêu cầu http?
user2499800

0
public boolean isInternetWorking(){
    try {
        int timeOut = 5000;
        Socket socket = new Socket();
        SocketAddress socketAddress = new InetSocketAddress("8.8.8.8",53);
        socket.connect(socketAddress,timeOut);
        socket.close();
        return true;
    } catch (IOException e) {
        //silent
    }
    return false;
}

Nó đại diện cho máy chủ nào? "8.8.8.8", 53
Junaed
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.