SocketTimeoutException,网络超时设置connectionTimeout和SoTimeout的区别

1.问题:

 java.net.SocketTimeoutException: Read timed out 

最近发现网站上某个下载功能经常不能使用,排查日志定位到这么一个报错,socket连接超时,导致文件下载失败

2.原代码:

报错代码在这一行,使用了一个http连接的工具类

String result = HttpClientUtils.get(HttpClientUtils.getHttpClient(), apiHttpUtil.getUrl(), params, (Map)null);

点进getHttpClient()方法,可以看到有两个getHttpClient方法,一个是无参的,一个可自定义soTimeout、connectionTimeout

原代码调用的是无参方法getHttpClient(),方法体中设置了soTimeout 1000,connectionTimeout 5000,那这两个参数是什么意思呢?

	public static HttpClient getHttpClient() {
    
    
        return getHttpClient(10000, 5000);
    }

    public static HttpClient getHttpClient(int soTimeout, int connectionTimeout) {
    
    
        DefaultHttpClient client = new DefaultHttpClient();
        client.getParams().setParameter("http.protocol.cookie-policy", "best-match");
        HttpParams myHttpParams = client.getParams();
        HttpConnectionParams.setConnectionTimeout(myHttpParams, connectionTimeout);
        HttpConnectionParams.setSoTimeout(myHttpParams, soTimeout);
        return client;
    }

3.源码分析:

soTimeout

在HttpConnectionParams的setSoTimeout方法,查看CoreConnectionPNames.SO_TIMEOUT的定义

/**
     * Sets value of the {@link CoreConnectionPNames#SO_TIMEOUT} parameter.
     *
     * @param params HTTP parameters.
     * @param timeout SO_TIMEOUT.
     */
    public static void setSoTimeout(final HttpParams params, final int timeout) {
    
    
        Args.notNull(params, "HTTP parameters");
        params.setIntParameter(CoreConnectionPNames.SO_TIMEOUT, timeout);

    }

SO_TIMEOUT表示http.socket.timeout的值,定义毫秒为单位的socket超时时间,

指的是,等待数据的时间,或者说是一次socket连接最大保持时间,

如果设为0值,表示可以无限等待

/**
     * Defines the socket timeout ({@code SO_TIMEOUT}) in milliseconds,
     * which is the timeout for waiting for data  or, put differently,
     * a maximum period inactivity between two consecutive data packets).
     * A timeout value of zero is interpreted as an infinite timeout.
     * <p>
     * This parameter expects a value of type {@link Integer}.
     * </p>
     * @see java.net.SocketOptions#SO_TIMEOUT
     */
    public static final String SO_TIMEOUT = "http.socket.timeout";

connectionTimeout

在HttpConnectionParams的setConnectionTimeout方法,查看CoreConnectionPNames.CONNECTION_TIMEOUT的定义

/**
     * Sets value of the {@link CoreConnectionPNames#CONNECTION_TIMEOUT}
     * parameter.
     *
     * @param params HTTP parameters.
     * @param timeout connect timeout.
     */
    public static void setConnectionTimeout(final HttpParams params, final int timeout) {
    
    
        Args.notNull(params, "HTTP parameters");
        params.setIntParameter(CoreConnectionPNames.CONNECTION_TIMEOUT, timeout);
    }

CONNECTION_TIMEOUT表示http.connection.timeout的值,定义毫秒为单位的连接前超时时间,

指的是,建立连接前最大保持时间,

如果设为0值,表示可以无限等待

/**
     * Determines the timeout in milliseconds until a connection is established.
     * A timeout value of zero is interpreted as an infinite timeout.
     * <p>
     * Please note this parameter can only be applied to connections that
     * are bound to a particular local address.
     * <p>
     * This parameter expects a value of type {@link Integer}.
     * </p>
     */
    public static final String CONNECTION_TIMEOUT = "http.connection.timeout";

区别

connection是建立连接请求到成功之间的限制时间,可以理解为你跟人打招呼到他反应的间隔

socket是建立连接之后保持会话的时间,理解为打完招呼之后,双方开始沟通到沟通结束的间隔

4.解决

所以要解决连接超时的问题,connection时间不用改(因为建立连接是成功了的),需要自定义socket超时时间,如果测试60s足够文件下载,就设置为60000

5.新代码:

String result = HttpClientUtils.get(HttpClientUtils.getHttpClient(60000, 5000), apiHttpUtil.getUrl(), params, (Map)null);

猜你喜欢

转载自blog.csdn.net/weixin_43859729/article/details/107955597