javax.net.ssl.SSLException:读取错误:ssl = 0x9524b800:系统调用期间的I/O错误,同级连接重置

Ric*_*ter 53 ssl android http retrofit okhttp

在过去的几周里,我们的客户开始看到100个这样的"SSLException错误 - 连接重置连接",我无法弄清楚为什么

  1. 我们在okhttp上使用Retrofit,没有特殊配置

    public class OkHttpClientProvider implements IOkHttpClientProvider {
    
        OkHttpClient okHttpClient;
    
        public OkHttpClientProvider() {
            this.okHttpClient = createClient();
        }
    
        public OkHttpClient getOkHttpClient() {
            return this.okHttpClient;
        }
    
        private OkHttpClient createClient() {
            return new OkHttpClient();
        }
    }
    
    Run Code Online (Sandbox Code Playgroud)

上述客户提供商是单身人士.RestAdapter是使用这个注入的客户端构建的(我们使用匕首) -

RestAdapter.Builder restAdapterBuilder = new RestAdapter.Builder()
                                        .setConverter(converter)
                                        .setEndpoint(networkRequestDetails.getServerUrl())
                                        .setClient(new OkClient(okHttpClientProvider.getOkHttpClient()))
                                        .setErrorHandler(new NetworkSynchronousErrorHandler(eventBus))
                                        );
Run Code Online (Sandbox Code Playgroud)

基于堆栈溢出解决方案,我发现了 -

  1. 服务器上的保持活动持续时间为180秒,OkHttp的默认值为300秒

  2. 服务器在其标头中返回"Connection:close",但客户端请求发送"Connection:keepAlive"

  3. 服务器支持TLS 1.0/1.1/1.2并使用Open SSL

  4. 我们的服务器最近已转移到另一个托管服务提供商的另一个地理位置,因此我不知道这些是否是DNS故障

  5. 我们尝试调整keepAlive之类的东西,在服务器上重新配置OpenSSL,但由于某种原因,Android客户端不断收到此错误

  6. 当您尝试使用应用程序发布内容或拉动刷新时,它会立即发生,并且不会出现任何延迟(在发生此异常之前,它甚至不会进入网络或延迟,这意味着连接已经断开).但尝试多次以某种方式"修复它",我们取得了成功.它会在以后再次发生

  7. 我们已经在服务器上使我们的DNS条目无效,看看这是否是由它引起的,但是没有帮助

  8. 它主要发生在LTE上,但我也在Wifi上看过它

我不想禁用keep alive,因为大多数现代客户都不这样做.此外,我们正在使用OkHttp 2.4,这是后冰淇淋三明治设备的一个问题,所以我希望它应该照顾这些潜在的网络问题.iOS客户端也获得了这些例外但接近100倍(iOS客户端使用AFNetworking 2.0).我正在努力寻找新的东西,在这一点上尝试,任何帮助/想法?

更新 - 通过okhttp添加完整堆栈跟踪

      retrofit.RetrofitError: Read error: ssl=0x9dd07200: I/O error during system call, Connection reset by peer
              at retrofit.RestAdapter$RestHandler.invokeRequest(RestAdapter.java:390)
              at retrofit.RestAdapter$RestHandler.invoke(RestAdapter.java:240)
              at java.lang.reflect.Proxy.invoke(Proxy.java:397)
              at $Proxy15.getAccessTokenUsingResourceOwnerPasswordCredentials(Unknown Source)
              at com.company.droid.repository.network.NetworkRepository.getAccessTokenUsingResourceOwnerPasswordCredentials(NetworkRepository.java:76)
              at com.company.droid.ui.login.LoginTask.doInBackground(LoginTask.java:88)
              at com.company.droid.ui.login.LoginTask.doInBackground(LoginTask.java:23)
              at android.os.AsyncTask$2.call(AsyncTask.java:292)
              at java.util.concurrent.FutureTask.run(FutureTask.java:237)
              at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1112)
              at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:587)
              at java.lang.Thread.run(Thread.java:818)
       Caused by: javax.net.ssl.SSLException: Read error: ssl=0x9dd07200: I/O error during system call, Connection reset by peer
              at com.android.org.conscrypt.NativeCrypto.SSL_read(Native Method)
              at com.android.org.conscrypt.OpenSSLSocketImpl$SSLInputStream.read(OpenSSLSocketImpl.java:699)
              at okio.Okio$2.read(Okio.java:137)
              at okio.AsyncTimeout$2.read(AsyncTimeout.java:211)
              at okio.RealBufferedSource.indexOf(RealBufferedSource.java:306)
              at okio.RealBufferedSource.indexOf(RealBufferedSource.java:300)
              at okio.RealBufferedSource.readUtf8LineStrict(RealBufferedSource.java:196)
              at com.squareup.okhttp.internal.http.HttpConnection.readResponse(HttpConnection.java:191)
              at com.squareup.okhttp.internal.http.HttpTransport.readResponseHeaders(HttpTransport.java:80)
              at com.squareup.okhttp.internal.http.HttpEngine.readNetworkResponse(HttpEngine.java:917)
              at com.squareup.okhttp.internal.http.HttpEngine.readResponse(HttpEngine.java:793)
              at com.squareup.okhttp.internal.huc.HttpURLConnectionImpl.execute(HttpURLConnectionImpl.java:439)
              at com.squareup.okhttp.internal.huc.HttpURLConnectionImpl.getResponse(HttpURLConnectionImpl.java:384)
              at com.squareup.okhttp.internal.huc.HttpURLConnectionImpl.getResponseCode(HttpURLConnectionImpl.java:497)
              at com.squareup.okhttp.internal.huc.DelegatingHttpsURLConnection.getResponseCode(DelegatingHttpsURLConnection.java:105)
              at com.squareup.okhttp.internal.huc.HttpsURLConnectionImpl.getResponseCode(HttpsURLConnectionImpl.java:25)
              at retrofit.client.UrlConnectionClient.readResponse(UrlConnectionClient.java:73)
              at retrofit.client.UrlConnectionClient.execute(UrlConnectionClient.java:38)
              at retrofit.RestAdapter$RestHandler.invokeRequest(RestAdapter.java:321)
              at retrofit.RestAdapter$RestHandler.invoke(RestAdapter.java:240)
              at java.lang.reflect.Proxy.invoke(Proxy.java:397)
              at $Proxy15.getAccessTokenUsingResourceOwnerPasswordCredentials(Unknown Source)
              at com.company.droid.repository.network.NetworkRepository.getAccessTokenUsingResourceOwnerPasswordCredentials(NetworkRepository.java:76)
              at com.company.droid.ui.login.LoginTask.doInBackground(LoginTask.java:88)
              at com.company.droid.ui.login.LoginTask.doInBackground(LoginTask.java:23)
              at android.os.AsyncTask$2.call(AsyncTask.java:292)
              at java.util.concurrent.FutureTask.run(FutureTask.java:237)
              at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1112)
              at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:587)
              at java.lang.Thread.run(Thread.java:818)
      ]}
Run Code Online (Sandbox Code Playgroud)

Dev*_*aja 90

最近我在处理一些遗留代码时遇到了这个问题.谷歌搜索后我发现问题无处不在,但没有任何具体的解决方案.我研究了异常消息的各个部分,并在下面进行了分析.

分析:

  1. SSLException:SSL(安全套接字层)发生异常,它javax.net.ssl在JDK(openJDK/oracleJDK/AndroidSDK)的包中实现
  2. Read error ssl=# I/O error during system call:从安全套接字读取时出错.它发生在使用本机系统库/驱动程序时.请注意,所有平台solaris,Windows等都有自己的套接字库,SSL使用它们.Windows使用WINSOCK库.
  3. Connection reset by peer:系统库(Solaris报告ECONNRESET,Windows报告WSAECONNRESET)报告此消息,数据传输中使用的套接字不再可用,因为远程主机强制关闭现有连接.需要在主机和客户端之间创建新的安全路径

原因:

理解这个问题,我尝试找到连接重置背后的原因,我想出了以下原因:

  • 远程主机上的对等应用程序突然停止,主机重新启动,主机或远程网络接口被禁用,或远程主机使用硬关闭.
  • 如果由于保持活动活动在一个或多个操作正在进行时检测到故障而导致连接中断,则也可能导致此错误.正在进行的操作失败,后续操作失败.Network dropped connection on reset(On Windows(WSAENETRESET))Connection reset by peer(On Windows(WSAECONNRESET))
  • 如果目标服务器受防火墙保护,在大多数情况下都是如此,则与端口关联的生存时间(TTL)或超时会在给定超时时强制关闭空闲连接.这是我们感兴趣的

解析度:

  1. 服务器端的事件,例如突然停止服务,重新启动,禁用网络接口,无法通过任何方式处理.
  2. 在服务器端,使用较高的生存时间(TTL)或超时值(如3600秒)为给定端口配置防火墙.
  3. 客户可以"尝试"保持网络活动,以避免或减少Connection reset by peer.
  4. 正常情况下,正在进行的网络流量会使连接保持活动状态并且不会经常出现问题/异常 强大的Wifi机会最少Connection reset by peer.
  5. 对于移动网络2G,3G和4G,其中分组数据传递是间歇性的并且取决于移动网络可用性,它可能不会重置服务器端的TTL定时器并导致进入Connection reset by peer.

以下是建议在各种论坛上设置以解决问题的术语

  • ConnectionTimeout:仅在超时时使用.如果主机需要时间来连接更高的值,则客户端会等待连接.
  • SoTimeout:套接字超时 - 它表示接收数据包以将连接视为活动的最长时间.如果在给定时间内未收到任何数据,则假定连接已停止/已断开.
  • Linger:当数据排队等待发送并且在套接字上调用close套接字函数时,不应该关闭套接字的时间.
  • TcpNoDelay:您是否要禁用保存和累积TCP数据包的缓冲区,并在达到阈值后发送它们?将此设置为true将跳过TCP缓冲,以便立即发送每个请求.网络中的减速可能是由于更小和更频繁的分组传输导致的网络流量增加引起的.

因此,上述参数都不能帮助保持网络活跃,从而无效.

我发现一个设置可能有助于解决这个功能的问题

setKeepAlive(true)
setSoKeepalive(HttpParams params, enableKeepalive="true") 
Run Code Online (Sandbox Code Playgroud)

我是如何解决我的问题的?

  • 设置 HttpConnectionParams.setSoKeepAlive(params, true)
  • 抓住SSLException并检查异常消息Connection reset by peer
  • 如果发现异常,请存储下载/读取进度并创建新连接.
  • 如果可能,继续下载/读取else重新启动下载

我希望细节有所帮助.快乐编码......


jay*_*itb 11

如果使用Nginx并遇到类似的问题,那么这可能会有所帮助:

在此sslTesturl上扫描您的域,并查看您的设备版本是否允许连接.

如果由于TLS支持而无法连接较低版本的设备(如<Android 4.4.2等),请尝试将此添加到您的Nginx配置文件中,

ssl_protocols TLSv1 TLSv1.1 TLSv1.2;
Run Code Online (Sandbox Code Playgroud)


小智 6

我们从今天早上开始也遇到了同样的问题,它已经解决了...希望这会有所帮助...

IIS 8上的SSL

  1. 昨天一切正常,昨晚在IIS站点上更新了我们的SSL。
  2. 在签出站点时,绑定到SSL时注意到IIS8有一个新的复选框Require Server Name Indication,但未选中它,因此在启用它之前已被选中。
  3. 那引发了问题。
  4. 回到IIS,禁用该复选框。...已解决问题!!!!

希望这可以帮助!!!