我试图点击一些外部API来获取一些数据。当数据量很小时,一切正常,但当API返回的数据大小很大时,我会得到 CONNECTION RESET 异常。下面的代码来自java类InterfaceHelper,我还在第i行标记了注释,我在异常[ 尝试从InputStream 中读取数据时] <。< / p>
我试图在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)
答案 0 :(得分:0)
我只是说这在某种程度上可能会产生误导。
现在关于问题本身。
All-in-all - 连接重置意味着由于某种原因,客户端和服务器之间的连接被破坏。例如,服务器决定关闭连接。 调试过程在这里真的很棘手,所以如果我是你, 我会尝试一些技巧,具体取决于你正在研究的环境:
删除SSL并使用普通HTTP。这样,您可以在中间放置代理并更好地分析网络流量。像Burp这样的东西可以在这里提供帮助。
尝试消除某些防火墙/代理/无论是出于自身原因而转储连接的可能性。也许值得在服务器的同一台机器上运行这个代码(当然,如果它是一个可行的选项)只是为了测试它如何与“localhost”一起工作,你知道。
我对这个相当低级别的API并不熟悉并知道它的所有怪癖。 但是也许你可以使用HttpClient,这样你就可以省去了解所有“低级”标志的必要性,也许它有些不对劲。
希望这有帮助
答案 1 :(得分:0)
connection.setRequestMethod( “GET”);
而是使用
获取方法connection.setRequestMethod( “POST”);
因为get方法限制发送数据。
答案 2 :(得分:0)
这显然不是真正的代码,正如我在上面的评论中所指出的那样,但是
connection.setRequestProperty("Content-Type","application/x-www-form-urlencoded");
connection.setDoOutput(true);
您不会发送任何输出,因此您根本不应该调用这些方法。 setDoOutput(true)
与setRequestMethod("GET");
相矛盾。
或者,发送一些输出。
答案 3 :(得分:0)
我试图一次又一次地调试它,这次调试时我发现从DataInputStream读取数据是罪魁祸首。
行dataInputStream.read()一次读取一个char,我必须将其转换为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); < / strong>即可。
现在我已经删除了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();
}