httpclient 解決 connection reset 問題
錯誤如下:
java.net.SocketException: Connection reset
at java.net.SocketOutputStream.socketWrite(SocketOutputStream.java:118)
at java.net.SocketOutputStream.write(SocketOutputStream.java:159)
atorg.apache.http.impl.io.SessionOutputBufferImpl.streamWrite(SessionOutputBufferImpl.java:124)
atorg.apache.http.impl.io.SessionOutputBufferImpl.flushBuffer(SessionOutputBufferImpl.java:136)
atorg.apache.http.impl.io.SessionOutputBufferImpl.write(SessionOutputBufferImpl.java:167)
at org.apache.http.impl.io.ContentLengthOutputStream.write(ContentLengthOutputStream.java:113)
atorg.apache.http.entity.mime.content.FileBody.writeTo(FileBody.java:121)
atorg.apache.http.entity.mime.AbstractMultipartForm.doWriteTo(AbstractMultipartForm.java:134)
at org.apache.http.entity.mime.AbstractMultipartForm.writeTo(AbstractMultipartForm.java:157)
atorg.apache.http.entity.mime.MultipartFormEntity.writeTo(MultipartFormEntity.java:113)
at org.apache.http.impl.DefaultBHttpClientConnection.sendRequestEntity(DefaultBHttpClientConnection.java:156)
atorg.apache.http.impl.conn.CPoolProxy.sendRequestEntity(CPoolProxy.java:162)
atorg.apache.http.protocol.HttpRequestExecutor.doSendRequest(HttpRequestExecutor.java:238)
at org.apache.http.protocol.HttpRequestExecutor.execute(HttpRequestExecutor.java:123)
atorg.apache.http.impl.execchain.MainClientExec.execute(MainClientExec.java:271)
atorg.apache.http.impl.execchain.ProtocolExec.execute(ProtocolExec.java:184)
atorg.apache.http.impl.execchain.RetryExec.execute(RetryExec.java:88)
atorg.apache.http.impl.execchain.RedirectExec.execute(RedirectExec.java:110)
atorg.apache.http.impl.client.InternalHttpClient.doExecute(InternalHttpClient.java:184)
atorg.apache.http.impl.client.CloseableHttpClient.execute(CloseableHttpClient.java:82)
atorg.apache.http.impl.client.CloseableHttpClient.execute(CloseableHttpClient.java:107)
解決方法:
1. 使用TCP短連結無效
httppost.setProtocolVersion(HttpVersion.HTTP_1_0);
httppost.addHeader(HTTP.CONN_DIRECTIVE, HTTP.CONN_CLOSE);
2.設定逾時時間
int timeout = 60;
RequestConfig defaultRequestConfig = RequestConfig.custom()
.setSocketTimeout(timeout * 1000)
.setConnectTimeout(timeout * 1000)
.setConnectionRequestTimeout(timeout * 1000)
.build();
3.使用 CloseableHttpResponse
CloseableHttpResponse response = null;
response = httpClient.execute(httpPost);
HttpEntity httpEntity = response.getEntity();
EntityUtils.consume(httpEntity); //按照官方文檔的說法:二者都釋放了才可以正常的釋放連結
response.close();
具體代碼如下:
package com.curiousby.cn.srpignbootdemo.util;
import java.io.IOException;
import java.security.KeyManagementException;
import java.security.KeyStoreException;
import java.security.NoSuchAlgorithmException;
import java.security.cert.CertificateException;
import java.security.cert.X509Certificate;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import javax.net.ssl.SSLContext;
import org.apache.http.HttpEntity;
import org.apache.http.HttpVersion;
import org.apache.http.NameValuePair;
import org.apache.http.client.config.RequestConfig;
import org.apache.http.client.entity.UrlEncodedFormEntity;
import org.apache.http.client.methods.CloseableHttpResponse;
import org.apache.http.client.methods.HttpPost;
import org.apache.http.conn.ssl.SSLConnectionSocketFactory;
import org.apache.http.conn.ssl.SSLContextBuilder;
import org.apache.http.conn.ssl.TrustStrategy;
import org.apache.http.impl.client.CloseableHttpClient;
import org.apache.http.impl.client.HttpClients;
import org.apache.http.message.BasicNameValuePair;
import org.apache.http.protocol.HTTP;
import org.apache.http.util.EntityUtils;
import org.apache.log4j.Logger;
public class HttpHelper {
private final static Logger logger = Logger.getLogger(HttpHelper.class);
public static final String CHARSET = "UTF-8";
private static CloseableHttpClient httpClient = createSSLInsecureClient();
public static final Integer HTTP_OK = 200;
public static final String CONTENT_TYPE_NAME = "Content-Type";
public static final String CONTENT_TYPE_JSON = "application/json;charset=UTF-8";
public static final String CONTENT_TYPE_XML = "text/xml;charset=UTF-8";
public static final String CONTENT_TYPE_FORM = "application/x-www-form-urlencoded;charset=UTF-8";
public static final String ACCEPT_NAME = "Accept";
public static final String ACCEPT = "application/json;charset=UTF-8";
public static final int TIMEOUT = 60;//這個要弄長點
public static String postUrl(String url, Map<String, Object> params) {
String result = null;
CloseableHttpResponse response = null; //傳回結果,釋放連結
List<NameValuePair> pairs = new ArrayList<NameValuePair>();
try {
if (params != null && !params.isEmpty()) {
for (Map.Entry<String, Object> entry : params.entrySet()) {
String value = Validator.get_obj_or_empty(entry.getValue()).toString();
if (value != null) {
pairs.add(new BasicNameValuePair(entry.getKey(), value));
}
}
}
RequestConfig defaultRequestConfig = RequestConfig.custom()
.setSocketTimeout(TIMEOUT * 1000)
.setConnectTimeout(TIMEOUT * 1000)
.setConnectionRequestTimeout(TIMEOUT * 1000)
.build();
HttpPost httpPost = new HttpPost(url);
httpPost.setProtocolVersion(HttpVersion.HTTP_1_0);
httpPost.addHeader(CONTENT_TYPE_NAME, CONTENT_TYPE_FORM);
httpPost.addHeader(ACCEPT_NAME, ACCEPT);
httpPost.addHeader(HTTP.CONN_DIRECTIVE, HTTP.CONN_CLOSE);
httpPost.setConfig(defaultRequestConfig);
httpPost.setEntity(new UrlEncodedFormEntity(pairs, CHARSET));
response = httpClient.execute(httpPost); //建立連結得到傳回結果
int statusCode = response.getStatusLine().getStatusCode(); //傳回的結果碼
if (statusCode != 200) {
httpPost.abort();
logger.error("===httphelper==httpclient===請求異常");
return null;
}
HttpEntity httpEntity = response.getEntity();
if (httpEntity == null) {
logger.error("===httphelper==httpclient===傳回結果異常");
return null;
} else {
result = EntityUtils.toString(httpEntity, CHARSET);
}
EntityUtils.consume(httpEntity); //按照官方文檔的說法:二者都釋放了才可以正常的釋放連結
response.close();
return result;
} catch (Exception e) {
logger.error("===httphelper==httpclient===請求錯誤"+e.getMessage()+",錯誤資訊"+e);
return null;
} finally {
if (response != null) {
try {
response.close();
} catch (IOException e) {
logger.error("===httphelper==httpclient===關閉流異常"+e.getMessage()+",錯誤資訊"+e);
}
}
}
}
public static CloseableHttpClient createSSLInsecureClient() {
try {
SSLContext sslContext = new SSLContextBuilder().loadTrustMaterial(null,
new TrustStrategy() {
public boolean isTrusted(X509Certificate[] chain, String authType)
throws CertificateException {
return true;
}
}).build();
SSLConnectionSocketFactory sslsf = new SSLConnectionSocketFactory(sslContext,
SSLConnectionSocketFactory.ALLOW_ALL_HOSTNAME_VERIFIER);
return HttpClients.custom().setMaxConnTotal(100).setMaxConnPerRoute(10)
.setSSLSocketFactory(sslsf).build();
} catch (KeyManagementException e) {
e.printStackTrace();
} catch (NoSuchAlgorithmException e) {
e.printStackTrace();
} catch (KeyStoreException e) {
e.printStackTrace();
}
return HttpClients.createDefault();
}
}
捐助開發者
在興趣的驅動下,寫一個
免費
的東西,有欣喜,也還有汗水,希望你喜歡我的作品,同時也能支援一下。 當然,有錢捧個錢場(支援支付寶和微信 以及扣扣群),沒錢捧個人場,謝謝各位。
個人首頁:
http://knight-black-bob.iteye.com/![](https://img.laitimes.com/img/_0nNw4CM6IyYiwiM6ICdiwiIn5GcuITY1IGNmZWYjZzNjNWOwgTY2YmM0ADM5QWZwAzNlFDOfdWbp9CXt92Yu4GZjlGbh5SZslmZxl3Lc9CX6MHc0RHaiojIsJye.png)
謝謝您的贊助,我會做的更好!