使用 Ktor HttpClient(CIO) websocket 发送内容时如何捕获 Broken pipe 异常?
How to catch Broken pipe exception when send something using Ktor HttpClient(CIO) websocket?
我在 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.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.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")
}
}
}
}
}
}
我通过参考 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);
}
}
效果很好。
我在 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.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.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")
}
}
}
}
}
}
我通过参考 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);
}
}
效果很好。