为了账号安全,请及时绑定邮箱和手机立即绑定

异常记录——Connection reset

标签:
Java

连接重置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版本,问题解决

本文由博客一文多发平台 OpenWrite 发布!

点击查看更多内容
TA 点赞

若觉得本文不错,就分享一下吧!

评论

作者其他优质文章

正在加载中
JAVA开发工程师
手记
粉丝
0
获赞与收藏
3

关注作者,订阅最新文章

阅读免费教程

  • 推荐
  • 评论
  • 收藏
  • 共同学习,写下你的评论
感谢您的支持,我会继续努力的~
扫码打赏,你说多少就多少
赞赏金额会直接到老师账户
支付方式
打开微信扫一扫,即可进行扫码打赏哦
今天注册有机会得

100积分直接送

付费专栏免费学

大额优惠券免费领

立即参与 放弃机会
意见反馈 帮助中心 APP下载
官方微信

举报

0/150
提交
取消