如何断开 OkHttp3 sse 连接?
How do I disconnect a OkHttp3 sse connection?
问题:
我正在尝试创建一个可以使用 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
class 的实现,以了解该实现与 RealEventSource
有何不同。我认为区别在于读取循环的条件:
RealEventSource
行https://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
}
比较
RealServerSentEvent
行 https://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
实现包括条件 if call.isCanceled()
在循环中,而 OkHttp3-sse
则没有。我怀疑这导致 OkHttp3-sse
不退出,但我可能弄错了。
或者,我是否在监督断开连接的预期方式?
您正确地使用了 API 并且 OkHttp 应该在取消调用时导致读取失败并出现 IOException。显然这并没有发生,我将其视为 OkHttp 中的错误。
后续步骤:将错误报告给 OkHttp。如果您可以使用可执行的测试用例来做到这一点,我会确保这个问题很快得到修复。
最终我发现连接可以通过调用正常关闭:
eventSource.cancel();
client.dispatcher().executorService().shutdown();
由于这不需要对库进行任何更改,因此我关闭了错误报告。
问题:
我正在尝试创建一个可以使用 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
class 的实现,以了解该实现与 RealEventSource
有何不同。我认为区别在于读取循环的条件:
RealEventSource
行https://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
}
比较
RealServerSentEvent
行 https://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
实现包括条件 if call.isCanceled()
在循环中,而 OkHttp3-sse
则没有。我怀疑这导致 OkHttp3-sse
不退出,但我可能弄错了。
或者,我是否在监督断开连接的预期方式?
您正确地使用了 API 并且 OkHttp 应该在取消调用时导致读取失败并出现 IOException。显然这并没有发生,我将其视为 OkHttp 中的错误。
后续步骤:将错误报告给 OkHttp。如果您可以使用可执行的测试用例来做到这一点,我会确保这个问题很快得到修复。
最终我发现连接可以通过调用正常关闭:
eventSource.cancel();
client.dispatcher().executorService().shutdown();
由于这不需要对库进行任何更改,因此我关闭了错误报告。