繁体   English   中英

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

[英]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)

也许只是古怪,但我发现您的帖子中有些“怪异”的东西。

  1. 您使用SSL连接(如出现在stacktrace中),但是在提供的示例中,这根本不是HTTPS。
  2. application / x-www-form-urlencoded标头通常用于POST请求。 有关此内容的完整说明,请点击此处

我只是说这可能在某种程度上引起误解。

现在关于问题本身。

All-in-all-连接重置意味着由于某种原因,客户端和服务器之间的连接已断开。 例如,服务器决定关闭连接。 调试过程在这里可能非常棘手,所以如果您是我,我会尝试两种技术,具体取决于您正在工作的环境:

  1. 删除SSL并使用纯HTTP。 这样,您可以在两者之间放置一个代理并更好地分析网络流量。 Burp之类的东西可以在这里提供帮助。

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

  3. 我不太熟悉这个较低级别的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.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM