[英]java.net.SocketException: Connection reset With HTTPConnection
我试图打一些外部API来获取一些数据。 当数据大小较小时,一切正常,但是当API返回的数据大小较大时,会出现CONNECTION RESET异常。 下面的代码来自Java类InterfaceHelper,并且在出现异常的行号处也标记了注释[ 尝试从InputStream读取数据时,它的位置 ]。
我试图在STACKOVERFLOW本身上搜索太多问题,但是找不到合适的答案。 因此,请不要将其标记为重复问题。 我想知道这个问题背后的原因是什么,什么是解决这个问题的正确方法。 如果您发现此问题重复,请先回答该问题,再将其标记为重复。 我赌你。
在下面找到我使用过的代码。 出于安全原因,URL是一些伪URL,因此我无法提及我使用的实际URL。
try{
URL url = new URL("http://example.com/someParams/SOME-ACCESS-TOKEN");
HttpURLConnection connection = (HttpURLConnection)url.openConnection();
connection.setRequestMethod("GET");
connection.setRequestProperty("Content-Type","application/x-www-form-urlencoded");
connection.setRequestProperty("Content-Language", "en-US");
connection.setRequestProperty("X-EXAMPLE-LOGIN", "XXXXXXXX");
connection.setRequestProperty("X-EXAMPLE-PASSWORD", "XXXXXX");
connection.setUseCaches(false);
connection.setDoInput(true);
connection.setDoOutput(true);
DataInputStream input = new DataInputStream(connection.getInputStream());
String ret = "";
if(input!=null){
for( int c = input.read(); c != -1; c = input.read() ) { //InterfaceHelper.java:695
ret = ret + String.valueOf((char)c);
}
}
if(input!=null)
input.close();
if(connection!=null)
connection.disconnect();
if(ret!=null && ret.length()>0){
return ret;
}
}catch(Exception e) {
e.printStackTrace();
}
这是我得到的例外
java.net.SocketException: Connection reset
at java.net.SocketInputStream.read(SocketInputStream.java:196)
at java.net.SocketInputStream.read(SocketInputStream.java:122)
at sun.security.ssl.InputRecord.readFully(InputRecord.java:442)
at sun.security.ssl.InputRecord.readV3Record(InputRecord.java:554)
at sun.security.ssl.InputRecord.read(InputRecord.java:509)
at sun.security.ssl.SSLSocketImpl.readRecord(SSLSocketImpl.java:927)
at sun.security.ssl.SSLSocketImpl.readDataRecord(SSLSocketImpl.java:884)
at sun.security.ssl.AppInputStream.read(AppInputStream.java:102)
at java.io.BufferedInputStream.fill(BufferedInputStream.java:235)
at java.io.BufferedInputStream.read1(BufferedInputStream.java:275)
at java.io.BufferedInputStream.read(BufferedInputStream.java:334)
at sun.net.www.http.ChunkedInputStream.fastRead(ChunkedInputStream.java:244)
at sun.net.www.http.ChunkedInputStream.read(ChunkedInputStream.java:689)
at java.io.FilterInputStream.read(FilterInputStream.java:133)
at sun.net.www.protocol.http.HttpURLConnection$HttpInputStream.read(HttpURLConnection.java:3053)
at sun.net.www.protocol.http.HttpURLConnection$HttpInputStream.read(HttpURLConnection.java:3047)
at sun.net.www.protocol.http.HttpURLConnection$HttpInputStream.read(HttpURLConnection.java:3035)
at java.io.FilterInputStream.read(FilterInputStream.java:83)
at com.lsa.akosha.util.InterfaceHelper.hitApiBrandWatch(InterfaceHelper.java:695)
at com.lsa.akosha.service.brand.BrandCronService.brandSentiments(BrandCronService.java:288)
at com.lsa.akosha.util.thread.BrandWatchCronConverse.executeInternal(BrandWatchCronConverse.java:60)
at org.springframework.scheduling.quartz.QuartzJobBean.execute(QuartzJobBean.java:113)
at org.quartz.core.JobRunShell.run(JobRunShell.java:213)
at org.quartz.simpl.SimpleThreadPool$WorkerThread.run(SimpleThreadPool.java:557)
也许只是古怪,但我发现您的帖子中有些“怪异”的东西。
我只是说这可能在某种程度上引起误解。
现在关于问题本身。
All-in-all-连接重置意味着由于某种原因,客户端和服务器之间的连接已断开。 例如,服务器决定关闭连接。 调试过程在这里可能非常棘手,所以如果您是我,我会尝试两种技术,具体取决于您正在工作的环境:
删除SSL并使用纯HTTP。 这样,您可以在两者之间放置一个代理并更好地分析网络流量。 Burp之类的东西可以在这里提供帮助。
尝试消除某些防火墙/代理/仅出于自身原因转储连接的可能性。 您知道,也许值得在与服务器同一台机器上运行此代码(当然,如果可行的话),只是为了测试它如何与“ localhost”一起工作。
我不太熟悉这个较低级别的API,并且不了解其所有怪癖。 但是也许您可以改用HttpClient,这样您就可以消除对所有“低级”标志的了解的需要,也许那里有些问题。
希望这可以帮助
connection.setRequestMethod( “GET”);
而是尝试使用方法
connection.setRequestMethod( “POST”);
因为get方法有发送数据的限制。
正如我在上面的评论中指出的那样,这显然不是真正的代码,但是
connection.setRequestProperty("Content-Type","application/x-www-form-urlencoded");
connection.setDoOutput(true);
您没有发送任何输出,因此根本不应该调用这些方法。 并且setDoOutput(true)
与setRequestMethod("GET");
相矛盾setRequestMethod("GET");
。
或者, 发送一些输出。
我尝试一次又一次地调试它,这一次在调试时我发现从DataInputStream读取数据是罪魁祸首。
行dataInputStream.read()一次读取一个字符,我必须将其转换为String。 下面是代码
String ret = "";
if(input!=null){
for( int c = input.read(); c != -1; c = input.read() ) { //InterfaceHelper.java:695
ret = ret + String.valueOf((char)c);
}
}
主要问题是我正在将数据读入int,然后将其转换为char,然后转换为String,即ret = ret + String.valueOf((char)c); 。
现在,我删除了DataInputStream并使用了BufferInputStream和使用了bufferInputStream.readLine(),它们直接从InputStream读取字符串中的行,因此没有类型转换可以节省大量时间从流中读取数据,因此直到连接和流到期时才读取数据,然后关闭两者。
这样我的问题就解决了。 我正在发布新代码,这可以帮助我解决问题。
try{
URL url = new URL("http://example.com/someParams/SOME-ACCESS-TOKEN");
HttpURLConnection connection = (HttpURLConnection)url.openConnection();
connection.setRequestMethod("GET");
connection.setRequestProperty("Content-Type","application/x-www-form-urlencoded");
connection.setRequestProperty("Content-Language", "en-US");
connection.setRequestProperty("X-EXAMPLE-LOGIN", "XXXXXXXX");
connection.setRequestProperty("X-EXAMPLE-PASSWORD", "XXXXXX");
connection.setUseCaches(false);
connection.setDoInput(true);
connection.setDoOutput(true);
connection.setConnectTimeout(99999999);
connection.setReadTimeout(99999999);
BufferedReader in = new BufferedReader(new InputStreamReader(connection.getInputStream()));
//DataInputStream input = new DataInputStream(connection.getInputStream());
String ret = "";
/* if(in!=null){
for( int c = input.read(); c != -1; c = input.read() ) {
ret = ret + String.valueOf((char)c);
if(input==null || connection==null)
break;
}
}*/
String inputLine;
while ((inputLine = in.readLine()) != null)
{
ret = ret + inputLine;
}
if(in!=null)
in.close();
if(connection!=null)
connection.disconnect();
if(ret!=null && ret.length()>0){
return ret;
}
}catch(Exception e) {
e.printStackTrace();
}
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.