简体   繁体   English

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

[英]java.net.SocketException: Connection reset With HTTPConnection

I am trying to hit some external API to fetch some data. 我试图打一些外部API来获取一些数据。 When the data size is small, everything works fine but when the size of data returned by the API is big I get CONNECTION RESET exception. 当数据大小较小时,一切正常,但是当API返回的数据大小较大时,会出现CONNECTION RESET异常。 The below code is from java class InterfaceHelper and I have also marked the comment at the line no where I am getting exception [ Its while trying to read data from InputStream ]. 下面的代码来自Java类InterfaceHelper,并且在出现异常的行号处也标记了注释[ 尝试从InputStream读取数据时,它的位置 ]。

I have tried to search so many question on STACKOVERFLOW itself but didn't find an appropriate answer. 我试图在STACKOVERFLOW本身上搜索太多问题,但是找不到合适的答案。 So please don't mark it as duplicate question. 因此,请不要将其标记为重复问题。 I want to know what is the reason behind this problem, and what is the proper solution for this problem. 我想知道这个问题背后的原因是什么,什么是解决这个问题的正确方法。 If you find this question as duplicate please answer it before marking it as duplicate. 如果您发现此问题重复,请先回答该问题,再将其标记为重复。 I dare you. 我赌你。

Find below my code which I have used. 在下面找到我使用过的代码。 URL is some dummy url as for security reason I cannot mention the actual URL I have used. 出于安全原因,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();
    } 

This the exception I get 这是我得到的例外

        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)

maybe its just quirks, but I've found some "weird" things in your post. 也许只是古怪,但我发现您的帖子中有些“怪异”的东西。

  1. You use SSL connection (as it appears in the stacktrace) but in the provided example this is no HTTPS at all. 您使用SSL连接(如出现在stacktrace中),但是在提供的示例中,这根本不是HTTPS。
  2. application/x-www-form-urlencoded header is usually used with POST requests. application / x-www-form-urlencoded标头通常用于POST请求。 Full explanation on this read here 有关此内容的完整说明,请点击此处

I'm just saying that this can be misleading to some extent. 我只是说这可能在某种程度上引起误解。

Now regarding the question itself. 现在关于问题本身。

All-in-all - connection reset means that for some reason the connection between the client and the server is broken. All-in-all-连接重置意味着由于某种原因,客户端和服务器之间的连接已断开。 For example, the server decides to close the connection. 例如,服务器决定关闭连接。 The debugging process can be really tricky here, so if I were you, I would have tried a couple of techniques, depending on environment you're working on: 调试过程在这里可能非常棘手,所以如果您是我,我会尝试两种技术,具体取决于您正在工作的环境:

  1. Remove SSL and work with plain HTTP. 删除SSL并使用纯HTTP。 This way you can put a proxy in-between and analyze the network traffic better. 这样,您可以在两者之间放置一个代理并更好地分析网络流量。 Stuff like Burp can help here. Burp之类的东西可以在这里提供帮助。

  2. Try to eliminate the possibility that some firewall/proxy/whatever just dumps the connection for its own reasons. 尝试消除某些防火墙/代理/仅出于自身原因转储连接的可能性。 Maybe it worth to run this code in the same machine with the server (of course if its a viable option) just for the sake of testing how this works with "localhost", you know. 您知道,也许值得在与服务器同一台机器上运行此代码(当然,如果可行的话),只是为了测试它如何与“ localhost”一起工作。

  3. I'm not really familiar with this fairly low level API and know all its quirks. 我不太熟悉这个较低级别的API,并且不了解其所有怪癖。 But maybe you can use HttpClient instead, this way you'll probably eliminate the need to know all the "low-level" flags, maybe its something wrong there. 但是也许您可以改用HttpClient,这样您就可以消除对所有“低级”标志的了解的需要,也许那里有些问题。

Hope this helps 希望这可以帮助

connection.setRequestMethod("GET"); connection.setRequestMethod( “GET”);

Instead get method try using 而是尝试使用方法

connection.setRequestMethod("POST"); connection.setRequestMethod( “POST”);

because get method has limit to send the data. 因为get方法有发送数据的限制。

This is clearly not the real code, as noted in my comment above, but 正如我在上面的评论中指出的那样,这显然不是真正的代码,但是

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

You aren't sending any output so you shouldn't be calling these methods at all. 您没有发送任何输出,因此根本不应该调用这些方法。 And setDoOutput(true) contradicts setRequestMethod("GET"); 并且setDoOutput(true)setRequestMethod("GET");相矛盾setRequestMethod("GET"); .

Alternatively, send some output. 或者, 发送一些输出。

I tried to debug it again and again, this time while debugging I found that reading data from DataInputStream is the culprit here. 我尝试一次又一次地调试它,这一次在调试时我发现从DataInputStream读取数据是罪魁祸首。

The line dataInputStream.read() reads one char at a time, and I have to convert it into String. 行dataInputStream.read()一次读取一个字符,我必须将其转换为String。 Below is the code 下面是代码

    String  ret = "";
    if(input!=null){
        for( int c = input.read(); c != -1; c = input.read() ) { //InterfaceHelper.java:695
            ret = ret + String.valueOf((char)c);
        }
    }

The main problem is that I am reading data into int and then convert it into char and then into String ie ret = ret + String.valueOf((char)c); 主要问题是我正在将数据读入int,然后将其转换为char,然后转换为String,即ret = ret + String.valueOf((char)c); .

Now I have removed the DataInputStream and used BufferInputStream and used bufferInputStream.readLine() which directly read's line in string from InputStream, so no type casting which saves lots of time in reading data from stream and hence till the time connection and stream expires it reads the data and then I close both. 现在,我删除了DataInputStream并使用了BufferInputStream和使用了bufferInputStream.readLine(),它们直接从InputStream读取字符串中的行,因此没有类型转换可以节省大量时间从流中读取数据,因此直到连接和流到期时才读取数据,然后关闭两者。

This way my problem is resolved. 这样我的问题就解决了。 I am posting my new code which helps me in solving my problem. 我正在发布新代码,这可以帮助我解决问题。

   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