java.net.SocketException:使用HTTPConnection重置连接

时间:2014-12-02 05:25:04

标签: java java-ee socket.io-java-client

我试图点击一些外部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)

4 个答案:

答案 0 :(得分:0)

也许它只是怪癖,但我在你的帖子中发现了一些“怪异”的东西。

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

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

    现在关于问题本身。

    All-in-all - 连接重置意味着由于某种原因,客户端和服务器之间的连接被破坏。例如,服务器决定关闭连接。 调试过程在这里真的很棘手,所以如果我是你, 我会尝试一些技巧,具体取决于你正在研究的环境:

    1. 删除SSL并使用普通HTTP。这样,您可以在中间放置代理并更好地分析网络流量。像Burp这样的东西可以在这里提供帮助。

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

    3. 我对这个相当低级别的API并不熟悉并知道它的所有怪癖。 但是也许你可以使用HttpClient,这样你就可以省去了解所有“低级”标志的必要性,也许它有些不对劲。

    4. 希望这有帮助

答案 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();
   }