如何使用 OkHttpClient 真正断开与 WebSocket 的连接?

Posted

技术标签:

【中文标题】如何使用 OkHttpClient 真正断开与 WebSocket 的连接?【英文标题】:How to really disconnect from WebSocket using OkHttpClient? 【发布时间】:2021-05-22 09:37:11 【问题描述】:

我正在尝试断开与 WebSocket 的连接,但它的侦听器仍然存在,我可以看到 Websocket 仍在使用 System.out 消息通过“OPEN/FAIL”消息重新创建。

一方面我尝试使用client.dispatcher().executorService().shutdown() 方法释放finally 块中的连接,但它拒绝其他未来的调用(因此它不适合),另一方面使用client.connectionPool().evictAll() 不要么帮助(即使我等待,因为它可能不会根据文档https://square.github.io/okhttp/4.x/okhttp/okhttp3/-ok-http-client/ 立即退出)

有WebSocketListener代码:

class WebSocketConnectionListener(
    private val updateConnectionValue: (internetConnection: Boolean) -> Unit,
    private val okHttpClient: OkHttpClient,
    private val urlAddress: String
) : WebSocketListener() 

    companion object 
        private const val NORMAL_CLOSURE_STATUS = 1000
    

    private var isConnected = true
    private var webSocketN: WebSocket? = null

    init 
        createWebSocket()
    

    override fun onOpen(webSocket: WebSocket, response: Response) 
        println("OPEN: $response.code")
        isConnected = true
        updateConnectionValue(true)
        reconnect(webSocket)
    

    override fun onFailure(webSocket: WebSocket, t: Throwable, response: Response?) 
        println("FAIL: $t")
        if (!isConnected) 
            updateConnectionValue(false)
        
        isConnected = false
        reconnect(webSocket)
    

    private fun createWebSocket() 
        val request = Request.Builder().url(urlAddress).build()
        webSocketN = okHttpClient.newWebSocket(request, this)
    

    private fun reconnect(webSocket: WebSocket) 
        webSocket.close(NORMAL_CLOSURE_STATUS, null)
        webSocketN?.close(NORMAL_CLOSURE_STATUS, "Connection closed")
        webSocketN = null

        Thread.sleep(3_000)
        createWebSocket()
    

有DataSource实现代码:

class InternetConnectionDataSourceImpl(
    private val okHttpClient: OkHttpClient,
    private val urlAddress: String
) : InternetConnectionDataSource 

    private fun createWebSocketListener(
        internetConnectionFlow: MutableStateFlow<Boolean>,
    ) = WebSocketConnectionListener(
        updateConnectionValue =  internetConnectionFlow.value = it ,
        okHttpClient = okHttpClient,
        urlAddress = urlAddress
    )

    override suspend fun checkConnection(): Flow<Boolean> =
        withContext(Dispatchers.IO) 
            val internetConnectionFlow = MutableStateFlow(true)
            createWebSocketListener(internetConnectionFlow)

            flow 
                try 
                    internetConnectionFlow.collect 
                        emit(it)
                    
                 finally 
                    println("finally")
                    okHttpClient.connectionPool.evictAll()
                
            
        

结果我在 logcat 中收到了这条消息

【问题讨论】:

【参考方案1】:

使用 WebSocket.close() 进行正常关闭或使用 cancel() 立即关闭。

https://square.github.io/okhttp/4.x/okhttp/okhttp3/-web-socket/

【讨论】:

以上是关于如何使用 OkHttpClient 真正断开与 WebSocket 的连接?的主要内容,如果未能解决你的问题,请参考以下文章

Java相关

如何告诉 OkHttpClient 忽略缓存并从服务器强制刷新?

Java相关问题整理

开发基础:OkHttpClient了解与封装

如何使用 okHttpClient 执行 graphql 查询?

如何在下面的 Apache HttpClient 代码中使用 OkHttpClient