2017-08-24 03:00:04.793 INFO 22781 --- [pool-7-thread-1]o.apache.http.impl.execchain.RetryExec : I/O exception (java.net.SocketException) caught when processingrequest to {}->http://xx:80: Connection reset
2017-08-24 03:00:04.794 INFO 22781 --- [pool-7-thread-1]o.apache.http.impl.execchain.RetryExec : Retrying request to {}->http://xx:80
2017-08-24 03:00:04.835 INFO 22781 --- [pool-7-thread-1]o.apache.http.impl.execchain.RetryExec : I/O exception (java.net.SocketException) caught when processingrequest to {}->http://xx:80: Connection reset
2017-08-24 03:00:04.835 INFO 22781 --- [pool-7-thread-1] o.apache.http.impl.execchain.RetryExec : Retrying request to{}->http://xx:80
2017-08-24 03:00:04.872 INFO 22781 --- [pool-7-thread-1]o.apache.http.impl.execchain.RetryExec : I/O exception (java.net.SocketException) caught when processingrequest to {}->http:/xx:80: Connection reset
2017-08-24 03:00:04.872 INFO 22781 --- [pool-7-thread-1]o.apache.http.impl.execchain.RetryExec : Retrying request to {}->http://xx:80
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短链接无效。
//最后的解决方案是客户端和服务器统一使用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. 下面的方法无效
浏览器发送请求到servlet,servlet处理时间太久,所以导致chrome浏览器出现ERR_CONNECTION_RESET错误
解决方案:
在相应servlet执行最后添加一句代码:
Thread.currentThread().join();
表示必须在当前线程执行完之后才返回页面到浏览器。
4. 客户端浏览器刷新,或关闭,就会出现上面的问题,
如果经常出现,就可能是你的系统的性能问题。
网络拥堵的改善也没法解决这种问题
linux服务增加下面的内容
#vi /etc/sysctl.conf
net.ipv4.tcp_syncookies=1
net.ipv4.tcp_tw_reuse=1
net.ipv4.tcp_tw_recycle=1
net.ipv4.tcp_fin_timeout=30
net.ipv4.tcp_keepalive_time=1800
net.ipv4.tcp_max_syn_backlog=4096
5.以为是多线程的问题,结果也不是。
6.以为是pdf文件是加密文件,结果也不是。
到底是什么原因呢。结果是httpClient一直没有处理好的问题,就如异常报的它还是调用了jvm底层
追查代码找到SocketInputStream.socketRead0((FileDescriptor fd, byte b[], int off,int len, int timeout)
意思大概为本地调用方法错误,也就是JVM管理的问题。开发者认为根本不是HttpClient的问题。
但事情还是得想办法解决。我最后还是使用java自带的HttpURLConnection上传数据和附件。
下面的代码来自于网络,但增加解决HttpURLConnection上传文件名乱码的问题。其它的跟网上的例子类似。
Maven引入:
<dependency>
<groupId>net.sf.jmimemagicgroupId>
<artifactId>jmimemagicartifactId>
<version>0.1.5version>
dependency>
代码如下:
import java.io.BufferedReader;
import java.io.DataInputStream;
import java.io.DataOutputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.net.HttpURLConnection;
import java.net.URL;
import java.net.URLEncoder;
import java.nio.ByteBuffer;
import java.nio.CharBuffer;
import java.nio.charset.Charset;
import java.util.List;
import org.apache.http.Consts;
import org.apache.http.util.ByteArrayBuffer;
import com.alibaba.fastjson.JSON;
import net.sf.jmimemagic.Magic;
import net.sf.jmimemagic.MagicMatch;
/**
* Java原生的API可用于发送HTTP请求,即java.net.URL、java.net.URLConnection,这些API很好用、很常用,
* 但不够简便;
*
* 1.通过统一资源定位器(java.net.URL)获取连接器(java.net.URLConnection) 2.设置请求的参数 3.发送请求
* 4.以输入流的形式获取返回内容 5.关闭输入流
*
* @author H__D
*
*/
public classHttpUploadURLConnectionUtils {
public staticfinal Charset UTF8_CHARSET = Consts.UTF_8;
public staticMessageDto snycWebSite(List
return uploadFile(transDto.getWebSiteUrl(), fileList,transDto);
}
private staticByteArrayBuffer encode(
final Charset charset, finalString string) {
final ByteBuffer encoded = charset.encode(CharBuffer.wrap(string));
final ByteArrayBuffer bab = newByteArrayBuffer(encoded.remaining());
bab.append(encoded.array(),encoded.position(), encoded.remaining());
return bab;
}
/**
* 多文件上传的方法
*
* @paramactionUrl:上传的路径
* @paramuploadFilePaths:需要上传的文件路径,数组
* @return
*/
public staticMessageDto uploadFile(String actionUrl,List
String end = "\r\n";
String twoHyphens = "--";
String boundary = "----------------------------123821742118716";
DataOutputStream douts = null;
InputStream inputStream = null;
InputStreamReader inputStreamReader =null;
BufferedReader reader = null;
StringBuffer resultBuffer = new StringBuffer();
String tempLine = null;
HttpURLConnection httpURLConnection =null;
try {
// 统一资源
URL url = newURL(actionUrl);
// http的连接类
httpURLConnection =(HttpURLConnection) url.openConnection();
httpURLConnection.setConnectTimeout(5000);
httpURLConnection.setReadTimeout(30000);
// 设置是否从httpUrlConnection读入,默认情况下是true;
httpURLConnection.setDoInput(true);
// 设置是否向httpUrlConnection输出
httpURLConnection.setDoOutput(true);
// Post 请求不能使用缓存
httpURLConnection.setUseCaches(false);
// 设定请求的方法,默认是GET
httpURLConnection.setRequestMethod("POST");
// 设置字符编码连接参数
httpURLConnection.setRequestProperty("Connection", "Keep-Alive");
// 设置字符编码
httpURLConnection.setRequestProperty("Charset", "UTF-8");
httpURLConnection.setRequestProperty("Content-Transfer-Encoding", "UTF-8");
httpURLConnection.setRequestProperty("User-Agent", "Mozilla/5.0(Windows; U; Windows NT 6.1; zh-CN; rv:1.9.2.6)");
// 设置请求内容类型
httpURLConnection.setRequestProperty("Content-Type", "multipart/form-data;boundary=" + boundary);
// 设置DataOutputStream
douts = newDataOutputStream(httpURLConnection.getOutputStream());
//加input输入框name=data value=transDto
StringBuffer strBuf = new StringBuffer();
strBuf.append(end).append(twoHyphens).append(boundary).append(end);
strBuf.append("Content-Disposition: form-data;name=\"data\"\r\n\r\n");
// StringBody userId = newStringBody(URLEncoder.encode(JSON.toJSONString(transDto), "utf-8"),ContentType.create( "text/plain", Consts.UTF_8));
strBuf.append(URLEncoder.encode(JSON.toJSONString(transDto), "utf-8"));
douts.writeBytes(strBuf.toString());
for (int i = 0; i < uploadFilePaths.size();i++) {
String filename= uploadFilePaths.get(i).getName();
MagicMatch match = Magic.getMagicMatch(uploadFilePaths.get(i),false, true);
String contentType= match.getMimeType();
StringBuffer sbinner = newStringBuffer();
sbinner.append(end).append(twoHyphens).append(boundary).append(end);
sbinner.append("Content-Disposition: form-data;name=\"file").append(i).append("\";filename=\"").append(filename).append("\"").append(end);
sbinner.append("Content-Type:" + contentType + "\r\n\r\n");
//解决附件文件名乱码的问题
ByteArrayBuffer b = encode(UTF8_CHARSET,sbinner.toString());
douts.write(b.buffer());
DataInputStream inStream =new DataInputStream(new FileInputStream(uploadFilePaths.get(i)));
byte[]buffer = newbyte[1024];
intlength = 0;
while((length = inStream.read(buffer)) != -1) {
douts.write(buffer, 0, length);
}
/*close streams */
inStream.close();
}
douts.writeBytes(end+twoHyphens+ boundary + twoHyphens+ end);
/* close streams */
douts.flush();
douts.close();
if (httpURLConnection.getResponseCode()>= 300) {
thrownew Exception(
"HTTP Request is not success, Response code is " + httpURLConnection.getResponseCode());
}
if(httpURLConnection.getResponseCode() ==HttpURLConnection.HTTP_OK) {
inputStream= httpURLConnection.getInputStream();
inputStreamReader= new InputStreamReader(inputStream);
reader= new BufferedReader(inputStreamReader);
tempLine= null;
resultBuffer= new StringBuffer();
while((tempLine = reader.readLine())!= null) {
resultBuffer.append(tempLine);
resultBuffer.append("\n");
}
}
} catch (Exception e) {
e.printStackTrace();
} finally {
httpURLConnection.disconnect();
}
return JSON.parseObject(resultBuffer.toString(), MessageDto.class);
}
}