当前位置: 首页 > 后端技术 > Java

java.io.IOException:现有连接被远程主机强行关闭,异常堆栈信息问题处理(屏蔽)!【邦隆隆原创】

时间:2023-04-02 09:32:54 Java

我们在使用Socket开发服务器相互通信的时候,应该都会遇到这个异常。一般情况下,这是由于客户端和服务器之间的网络异常或强行断开造成的,如下所示:java.io.IOException:现有连接被远程主机强行关闭。在sun.nio.ch.SocketDispatcher.read0(NativeMethod)在sun.nio.ch.SocketDispatcher.read(SocketDispatcher.java:43)在sun.nio.ch.IOUtil.readIntoNativeBuffer(IOUtil.java:223)在sun.nio.ch.IOUtil.read(IOUtil.java:192)在sun.nio.ch.SocketChannelImpl.read(SocketChannelImpl.java:380)在io.netty.buffer.PooledByteBuf.setBytes(PooledByteBuf.java:253)在io.netty.buffer.AbstractByteBuf.writeBytes(AbstractByteBuf.java:1132)在io.netty.channel.socket.nio.NioSocketChannel.doReadBytes(NioSocketChannel.java:350)在io.netty.channel.nio.AbstractNioByteChannel$NioByteUnsafe。在io.netty.channel.nio.NioEventLoop.processSelectedKey(NioEventLoop.java:719)在io.netty.channel.nio.NioEventLoop.processSelectedKeysOptimized(NioEventLoop.java:655)在io.netty读取(AbstractNioByteChannel.java:151).channel.nio.NioEventLoop.processSelectedKeys(NioEventLoop.java:581)在io.netty.channel.nio.NioEventLoop.run(NioEventLoop.java:493)在io.netty.util.concurrent.SingleThreadEventExecutor$4.run(SingleThreadEventExecutor.java:989)在io.netty.util.internal.ThreadExecutorMap$2.run(ThreadExecutorMap.java:74)在io.netty.util.concurrent.FastThreadLocalRunnable.run(FastThreadLocalRunnable.java:30)atjava.lang.Thread.run(Thread.java:748)在网上找了半天也没找到处理(屏蔽)异常的方法,于是自己动手,丰衣足食!通过查看源码,定位到打印异常的位置为堆栈信息:从名字就可以看出这是默认的异常监听类,它继承了ExceptionListenerAdapter,ExceptionListenerAdapter实现了ExceptionListener接口。接口代码如下:packagecom.corundumstudio。socketio.listener;importio.netty.channel.ChannelHandlerContext;importjava.util.List;importcom.corundumstudio.socketio.SocketIOClient;publicinterfaceExceptionListener{voidonEventException(Exceptione,Listargs,SocketIOClientclient);voidonDisconnectException(Exceptione,SocketIOClient客户端);voidonConnectException(Exceptione,SocketIOClient客户端);voidonPingException(Exceptione,SocketIOClient客户端);booleanexceptionCaught(ChannelHandlerContextctx,Throwablee)throwsException;}如果我们要屏蔽这个异常(栈信息),需要重新实现这个接口,然后重写exceptionCaught方法新建MyDefaultExceptionListener类继承ExceptionListenerAdapter,直接上代码:@Slf4jpublicclassMyDefaultExceptionListenerextendsExceptionListenerAdapter{publicMyDefaultExceptionListener(){super();}@OverridepublicvoidonEventException(Exceptione,Listargs,SocketIOClientclient){log.error(e.getMessage());}@OverridepublicvoidonDisconnectException(Exceptione,SocketIOClientclient){log.error(e.getMessage());}@OverridepublicvoidonConnectException(Exceptione,SocketIOClientclient){log.error(e.getMessage());}@OverridepublicvoidonPingException(Exceptione,SocketIOClientclient){log.error(e.getMessage());}@OverridepublicbooleanexceptionCaught(ChannelHandlerContextctx,Throwablee){log.error("Error:"+e.getMessage());ctx.close();返回真;}}为此,如果发生异常,则不会打印堆栈信息。接下来我们在Socket的初始化配置类中进行设置,示例代码:com.corundumstudio.socketio.Configurationconfiguration=newcom.corundumstudio.socketio.Configuration();////其他配置项省略///configuration.setExceptionListener(newMyDefaultExceptionListener());////其他配置项省略///returnnewSocketIOServer(configuration);这里有一个坑需要注意,不要给SocketIOServer添加监听器,是不行的。至此,异常覆盖就完成了。注:本文使用netty-socketio作为服务端。引入的版本为:com.corundumstudio.socketionetty-socketio1.7.19完成后,日志最终打印效果如下,不再有堆栈信息: