使用 Ktor HttpClient(CIO) websocket 发送内容时如何捕获 Broken pipe 异常?
Posted
技术标签:
【中文标题】使用 Ktor HttpClient(CIO) websocket 发送内容时如何捕获 Broken pipe 异常?【英文标题】:How to catch Broken pipe exception when send something using Ktor HttpClient(CIO) websocket? 【发布时间】:2021-06-12 14:48:23 【问题描述】:我正在 android 8 中使用 Ktor 1.2.5 和 Kotlin 1.3.61 开发网络应用程序
当 netty websocket 服务器像最近的应用程序清理一样不正常地关闭时,websocket 客户端不会收到任何事件。 当时,如果websocket客户端向服务器发送一些东西,那么App在发生Broken pope异常后就崩溃了。 但是,这个 Broken pipe 异常不会在发送时捕获。 在哪里捕获 Broken pipe 异常?
这里是异常日志
E/AndroidRuntime: FATAL EXCEPTION: Thread-6
Process: com.example.chatkt1, PID: 805
java.io.IOException: Broken pipe
at sun.nio.ch.FileDispatcherImpl.write0(Native Method)
at sun.nio.ch.SocketDispatcher.write(SocketDispatcher.java:55)
at sun.nio.ch.IOUtil.writeFromNativeBuffer(IOUtil.java:93)
at sun.nio.ch.IOUtil.write(IOUtil.java:51)
at sun.nio.ch.SocketChannelImpl.write(SocketChannelImpl.java:512)
at io.ktor.network.sockets.CIOWriterKt$attachForWritingDirectImpl$1$1.invokeSuspend(CIOWriter.kt:75)
at kotlin.coroutines.jvm.internal.BaseContinuationImpl.resumeWith(ContinuationImpl.kt:33)
at kotlinx.coroutines.DispatchedContinuation.resumeWith(Dispatched.kt:108)
at kotlinx.coroutines.io.internal.CancellableReusableContinuation.resumeWith(CancellableReusableContinuation.kt:93)
at kotlinx.coroutines.io.ByteBufferChannel.resumeReadOp(ByteBufferChannel.kt:2211)
at kotlinx.coroutines.io.ByteBufferChannel.flushImpl(ByteBufferChannel.kt:156)
at kotlinx.coroutines.io.ByteBufferChannel.flush(ByteBufferChannel.kt:162)
at io.ktor.http.cio.websocket.WebSocketWriter.drainQueueAndSerialize(WebSocketWriter.kt:108)
at io.ktor.http.cio.websocket.WebSocketWriter.writeLoop(WebSocketWriter.kt:47)
at io.ktor.http.cio.websocket.WebSocketWriter$writeLoop$1.invokeSuspend(Unknown Source:12)
at kotlin.coroutines.jvm.internal.BaseContinuationImpl.resumeWith(ContinuationImpl.kt:33)
at kotlinx.coroutines.DispatchedTask.run(Dispatched.kt:241)
at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1167)
at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:641)
at java.lang.Thread.run(Thread.java:764)
这里是 websocket 客户端代码
fun sendToServer(message: String)
if(session != null)
CoroutineScope(Dispatchers.IO).launch
mutex.withLock
try
session!!.send(message)
session!!.flush()
catch (e: IOException)
if (e.message.equals("Broken pipe"))
println("catch Broken pipe exception")
【问题讨论】:
作为一种解决方法,您可以为所有线程设置一个异常处理程序docs.oracle.com/javase/7/docs/api/java/lang/…。 【参考方案1】:我通过引用 Aleksei Tirman 的评论解决了这个问题。
val old = Thread.setDefaultUncaughtExceptionHandler _, e ->
if (e is java.io.IOException && e.message.equals("Broken pipe"))
println("catch Broken pipe exception")
else
android.os.Process.killProcess(android.os.Process.myPid())
exitProcess(10);
效果很好。
【讨论】:
以上是关于使用 Ktor HttpClient(CIO) websocket 发送内容时如何捕获 Broken pipe 异常?的主要内容,如果未能解决你的问题,请参考以下文章
如何在 Multiplatform Ktor 和 Coil 之间共享 HttpClient?
Ktor HttpClient 在 runBlocking 中挂起
如何使用针对 linuxX64 的 ktor-client-core 修复“未解决的参考:HttpClient”