2014-12-02 76 views
1

我试图打一些外部API来获取一些数据。当数据量很小时,一切正常,但是当API返回的数据量很大时,我会得到一个例外情况:CONNECTION RESET例外。下面的代码是从java类InterfaceHelper和我也标记了注释在行我没有在哪里得到异常[它试图从InputStream]读取数据]。java.net.SocketException:使用HTTPConnection重置连接

我试图在STACKOVERFLOW本身上搜索这么多问题,但没有找到合适的答案。所以请不要将其标记为重复的问题。我想知道这个问题背后的原因是什么,这个问题的解决方案是什么。如果您发现此问题为重复,请在将其标记为重复之前回答。我赌你。

查找下面我已经使用过的代码。由于安全原因,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

尝试调试代码,也许你会发现你的问题 – 2014-12-02 05:25:58

+0

我已经尝试过了,但它总是在抛出异常“DataInputStream所输入=新DataInputStream类(connection.getInputStream());”但是在打印堆栈跟踪中,它始终会在尝试读取时发生异常,例如for循环 – user2531799 2014-12-02 05:31:06

+0

在其他一些机器上尝试此代码(或者可能通过转向反病毒)。 – jsjunkie 2014-12-02 05:38:32

回答

0

我试图一次又一次地调试它,这次调试时我发现从DataInputStream读取数据是罪魁祸首。

line dataInputStream.read()每次读取一个字符,我必须将其转换为字符串。下面是代码

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然后进入字符串即RET =保留+将String.valueOf((char)的C);

现在我已经删除了DataInputStream并使用了BufferInputStream并使用了直接从InputStream中读取字符串的bufferInputStream.readLine(),所以没有类型转换可以节省大量时间从流中读取数据,因此直到时间连接和数据流会过期读取数据,然后关闭两者。

这样我的问题就解决了。我张贴我的新代码,这有助于我解决我的问题。

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(); 
    } 
+0

不是。这些都不会导致连接重置。 – EJP 2014-12-04 21:07:23

+0

@EJP:我正在从inputstream右边读取数据。当我从DataInputStream中读取数据时,我正在读取每个字符并转换为字符串,这需要花费时间进行类型转换,但是当我使用bufferReader时,我正在读取整行,它直接读取字符串中的数据,不会在内部完成类型转换或类型转换,类型转换。所以它解决了我的问题。 Connection复位的主要原因是我正在读取已关闭的Stream中的数据,并且close之后的原因是它在从流中读取数据时的超时 – user2531799 2014-12-05 04:47:17

0

也许它只是怪癖,但我发现在您的文章有些 “奇怪” 的事情。

  1. 您使用SSL连接(因为它出现在堆栈跟踪中),但在提供的示例中,根本没有HTTPS。
  2. application/x-www-form-urlencoded标头通常与POST请求一起使用。关于此阅读的完整说明here

我只是说这可能会在某种程度上产生误导。

现在关于这个问题本身。

全部连接重置意味着由于某种原因客户端与服务器之间的连接中断。例如,服务器决定关闭连接。 调试过程中可以很麻烦,在这里,所以如果我是你,我 会尝试一对夫妇的技术,根据环境而定你的工作:

  1. 删除SSL,并与普通的HTTP工作。通过这种方式,您可以放置​​代理,并更好地分析网络流量。像Burp这样的东西可以在这里帮助。

  2. 尝试消除某些防火墙/代理/任何只是为了自己的原因转储连接的可能性。也许值得在与服务器相同的机器上运行这个代码(当然如果它是一个可行的选项),只是为了测试它如何与“localhost”协同工作,你知道的。

  3. 我对这个相当低级的API并不是很熟悉,并且知道它的所有怪癖。 但是也许你可以使用HttpClient来代替,这样你可能就不需要知道所有的“低级”标志了,也许它在那里出错了。

希望这有助于

0

connection.setRequestMethod( “GET”);

相反get方法尝试使用

connection.setRequestMethod( “POST”);

因为get方法有限制发送数据。

+0

但是他没有发送任何数据;并且调用'connection.setDoOutput(true);'将请求方法设置为' POST'' – EJP 2014-12-02 06:11:28

+0

我正在从服务器读取数据,我没有发布它,所以设置POST不是真正的解决方案 – user2531799 2014-12-02 06:41:12

+0

@ user2531799那么,为什么你正在调用'setRequestMethod()'并设置'“Content-Type”if你不发送任何内容? – EJP 2014-12-02 07:22:17

0

这显然不是真正的代码,如我的评论指出以上,但

connection.setRequestProperty("Content-Type","application/x-www-form-urlencoded"); 
connection.setDoOutput(true); 

您没有发出任何输出,所以你不应该在所有调用这些方法。和setDoOutput(true)矛盾setRequestMethod("GET");

或者,发送一些输出。

+0

它因为我已经删除了安全凭证代码... – user2531799 2014-12-02 06:22:53

+0

我对你发布的代码发表评论。如果你想对你真实的代码发表评论,请发布。删除安全证书代码并不能解释为什么你要调用上面列出的两种方法。我会说你的服务器已经拒绝了你的凭证,但是我们只能猜测你是否遗漏了你的代码的相关部分。你不需要发布实际的凭证值,只需要'xxx'和'yyy'就可以了。但是你必须发布真实的代码。您甚至没有发布HTTPS网址。你在这里期待很多。 – EJP 2014-12-02 07:20:32

相关问题