如何断开OkHttp3 sse连接?

时间:2019-10-08 18:46:29

标签: okhttp

问题:

我正在尝试创建一个客户端,该客户端可以使用SSE(服务器发送的事件)从服务器接收事件,并且我使用OkHttp3与OkHttp3-sse库(com.squareup.okhttp3: okhttp:4.1.0&com.squareup.okhttp3:okhttp-sse:4.1.0)。 我能够连接到服务器并很好地接收事件,但是在某个时间点,我想断开客户端连接并关闭我的应用程序。那就是问题所在。连接已关闭,但应用程序未关闭,可能是由于ConnectionPool未关闭。

尝试:

由于几乎没有任何关于OkHttp3-sse库使用的文档,因此我尝试从代码中反向工程该怎么做。我试图:

  • 呼叫RealEventSource.cancel(),它正在断开连接,但挂在线程上
  • 呼叫OkHttpClient.dispatcher().cancelAll(),该电话也正在断开连接,但仍挂在线程上
  • 呼叫Response.close()传递给EventSourceListener.onOpen()

发现:

作为替代方案,我查看了https://github.com/heremaps/oksse,该调用具有RealServerSentEvent.close()的调用,该调用正在执行预期的操作。它关闭连接并停止所有线程,从而允许应用程序完全关闭。 我查看了RealServerSentEvent类的实现,以了解实现与RealEventSource有何不同。我认为区别在于读取循环的条件:

RealEventSourcehttps://github.com/square/okhttp/blob/master/okhttp-sse/src/main/java/okhttp3/internal/sse/RealEventSource.kt#L75行:

      try {
        listener.onOpen(this, response)
        while (reader.processNextEvent()) {
        }
      } catch (e: Exception) {
        listener.onFailure(this, e, response)
        return
      }

RealServerSentEventhttps://github.com/heremaps/oksse/blob/master/src/main/java/com/here/oksse/RealServerSentEvent.java#L94

            listener.onOpen(this, response);

            //noinspection StatementWithEmptyBody
            while (call != null && !call.isCanceled() && sseReader.read()) {
            }

OkSSE实现包含循环中call.isCanceled()的条件,而OkHttp3-sse则没有。我怀疑这导致OkHttp3-sse无法退出,但我可能会误会。

或者,我是否正在监督断开连接的预期方式?

2 个答案:

答案 0 :(得分:3)

您正确使用了API,并且取消调用后,OkHttp应该导致读取失败并出现IOException。显然,这没有发生,我在OkHttp中将其视为错误。

下一步:将错误报告给OkHttp。如果您可以使用可执行的测试用例来做到这一点,那么我将确保它很快得到真正修复。

答案 1 :(得分:2)

最终我发现可以通过调用来正常关闭连接

eventSource.cancel();
client.dispatcher().executorService().shutdown();

由于这不需要对库进行任何更改,因此我关闭了错误报告。