異常記錄 Connection reset


連接重置Connection reset

異常java.net.SocketException: Connection reset

詳細信息

java.net.SocketException: Connection reset
	at java.net.SocketInputStream.read(SocketInputStream.java:210)
	at java.net.SocketInputStream.read(SocketInputStream.java:141)
	at sun.security.ssl.InputRecord.readFully(InputRecord.java:465)
	at sun.security.ssl.InputRecord.read(InputRecord.java:503)
	at sun.security.ssl.SSLSocketImpl.readRecord(SSLSocketImpl.java:975)
	at sun.security.ssl.SSLSocketImpl.performInitialHandshake(SSLSocketImpl.java:1367)
	at sun.security.ssl.SSLSocketImpl.startHandshake(SSLSocketImpl.java:1395)
	at sun.security.ssl.SSLSocketImpl.startHandshake(SSLSocketImpl.java:1379)
	at org.apache.http.conn.ssl.SSLConnectionSocketFactory.createLayeredSocket(SSLConnectionSocketFactory.java:396)
	at org.apache.http.conn.ssl.SSLConnectionSocketFactory.connectSocket(SSLConnectionSocketFactory.java:355)
	at org.apache.http.impl.conn.DefaultHttpClientConnectionOperator.connect(DefaultHttpClientConnectionOperator.java:142)
	at org.apache.http.impl.conn.PoolingHttpClientConnectionManager.connect(PoolingHttpClientConnectionManager.java:373)
	at org.apache.http.impl.execchain.MainClientExec.establishRoute(MainClientExec.java:381)
	at org.apache.http.impl.execchain.MainClientExec.execute(MainClientExec.java:237)
	at org.apache.http.impl.execchain.ProtocolExec.execute(ProtocolExec.java:185)
	at org.apache.http.impl.execchain.RetryExec.execute(RetryExec.java:89)
	at org.apache.http.impl.execchain.RedirectExec.execute(RedirectExec.java:111)
	at org.apache.http.impl.client.InternalHttpClient.doExecute(InternalHttpClient.java:185)
	at org.apache.http.impl.client.CloseableHttpClient.execute(CloseableHttpClient.java:83)
	at org.apache.http.impl.client.CloseableHttpClient.execute(CloseableHttpClient.java:108)
	at com.senthink.www.oc.http.HttpRequester.execute(HttpRequester.java:170)

場景回溯

  1. 首次請求 首次向電信物聯網平台API發送Https請求時報錯
  2. 未得到響應
  3. 只有Soctet異常:Connection Reset

出現原因

Connection Reset——其中一端主動斷開連接

Connection Reset是在建立TCP連接之后,其中一方的TCP標志位使用了Reset標志主動重置了連接

客戶端Or服務器端

而我這里既然是客戶端報的錯誤信息,那勢必是服務器主動斷開了連接

為什么它要斷開連接

服務器主動斷開連接的原因:

  • 服務器異常

  • 服務器和客戶端長短連接不匹配

  • Https連接,服務器和客戶端的TLS版本不一致

原因排查

  • 服務器異常 電信作為三大運營商,它的服務器出現異常的可能性不大
  • 長短連接不匹配 如果是長短連接不匹配,那么也是第一次響應之后短連接方斷開連接,而我跟本沒有收到響應,因此可以排除長短連接不一致的情況
  • Https連接,TLS版本不一致

用排除法分析出:此時連接重置的原因是TLS版本不一致

解決方法

  • 查服務器端支持的TLS版本,然后切換請求客戶端的TLS版本

    可以查指定域名TLS版本的網站

  • 試出來服務器端支持的TLS版本

    1. 打開Http客戶端的配置(我用的是HttpClient,它的TLS配置在SSL連接工廠中的String數組參數)

      public CloseableHttpClient closeableHttpClient() throws Exception {
          // Trust own CA and all self-signed certs
          String userDir = System.getProperty("user.dir");
          SSLContext sslcontext = SSLContexts.custom()
              .loadTrustMaterial(
              new File(userDir + ocSetting.getCertPathCA()),
              ocSetting.getCertPasswordCA().toCharArray(),
              new TrustSelfSignedStrategy())
              .loadKeyMaterial(
              new File(userDir + ocSetting.getCertPathOutGoing()),
              ocSetting.getCertPasswordOutGoing().toCharArray(),
              ocSetting.getCertPasswordOutGoing().toCharArray())
              .build();
          // Allow TLSv1 protocol only
          //這里的問題,這里配置只允許TLSv1版本
          SSLConnectionSocketFactory sslsf = new SSLConnectionSocketFactory(
              sslcontext,
              new String[] { "TLSv1"},
              //new String[] {"TLSv1","TLSv1.1","TLSv1.2",瘋狂往里加}
              null,
              SSLConnectionSocketFactory.getDefaultHostnameVerifier());
      
          return HttpClients.custom().setSSLSocketFactory(sslsf).build();
      }
      
    2. 以此切換TLS版本,直到不再出現Connection Reset

      TLS版本有哪些?,這個在sun.security.ssl.ProtocolVersion中可以看到

      static final ProtocolVersion NONE = new ProtocolVersion(-1, "NONE");
      static final ProtocolVersion SSL20Hello = new ProtocolVersion(2, "SSLv2Hello");
      static final ProtocolVersion SSL30 = new ProtocolVersion(768, "SSLv3");
      static final ProtocolVersion TLS10 = new ProtocolVersion(769, "TLSv1");
      static final ProtocolVersion TLS11 = new ProtocolVersion(770, "TLSv1.1");
      static final ProtocolVersion TLS12 = new ProtocolVersion(771, "TLSv1.2");
      
    3. 換上服務器支持的TLS版本,問題解決


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM