我用netty做一个文件传输,当客户端下载文件时,服务端传文件。服务端传文件的代码如下:
final ChunkedStream chunkedStream = new ChunkedStream(fis); ctx.channel().writeAndFlush(chunkedStream).addListener(new ChannelFutureListener() { @Override public void operationComplete(ChannelFuture future) throws Exception { if(!future.isSuccess()) { logger.debug("File send timeout"); } if (ctx != null ) { if (ctx.channel().isActive()) { System.out.println("close again?"); ctx.close(); } } if (chunkedStream != null) { chunkedStream.close(); } if (fis != null) { try { fis.close(); } catch (IOException e) { } } } });
问题出现在以下场景:我写了一个下载超时控制的handler,当超过指定时间后,会触发一个我自定义的Exception。然后我在exceptionCaught里捕获它,并关闭连接。这时,服务端还继续着向客户端传文件,连接关闭后,上面代码的operationComplete方法会被触发,并且future.isSuccess()返回false。operationComplete方法里面的代码执行完后,就开始出错了。错误信息栈如下所示:
16:29:55.637-[WARN ] Lsr-FileTransferService-IoProcessor-73 DefaultPromise - An exception was thrown by io.netty.handler.stream.ChunkedWriteHandler$5.operationComplete()
java.lang.IllegalStateException: complete already: DefaultChannelPromise@82acef(failure(java.nio.channels.ClosedChannelException)
at io.netty.util.concurrent.DefaultPromise.setFailure(DefaultPromise.java:401) [netty-all-4.0.10.Final.jar:na]
at io.netty.channel.DefaultChannelPromise.setFailure(DefaultChannelPromise.java:87) ~[netty-all-4.0.10.Final.jar:na]
at io.netty.handler.stream.ChunkedWriteHandler$PendingWrite.fail(ChunkedWriteHandler.java:354) ~[netty-all-4.0.10.Final.jar:na]
at io.netty.handler.stream.ChunkedWriteHandler$5.operationComplete(ChunkedWriteHandler.java:306) ~[netty-all-4.0.10.Final.jar:na]
at io.netty.handler.stream.ChunkedWriteHandler$5.operationComplete(ChunkedWriteHandler.java:301) ~[netty-all-4.0.10.Final.jar:na]
at io.netty.util.concurrent.DefaultPromise.notifyListener0(DefaultPromise.java:621) [netty-all-4.0.10.Final.jar:na]
at io.netty.util.concurrent.DefaultPromise.notifyListeners(DefaultPromise.java:548) [netty-all-4.0.10.Final.jar:na]
at io.netty.util.concurrent.DefaultPromise.tryFailure(DefaultPromise.java:407) [netty-all-4.0.10.Final.jar:na]
at io.netty.channel.ChannelOutboundBuffer.safeFail(ChannelOutboundBuffer.java:508) [netty-all-4.0.10.Final.jar:na]
at io.netty.channel.ChannelOutboundBuffer.remove(ChannelOutboundBuffer.java:296) [netty-all-4.0.10.Final.jar:na]
at io.netty.channel.ChannelOutboundBuffer.failFlushed(ChannelOutboundBuffer.java:440) [netty-all-4.0.10.Final.jar:na]
at io.netty.channel.AbstractChannel$AbstractUnsafe.close(AbstractChannel.java:550) [netty-all-4.0.10.Final.jar:na]
at io.netty.channel.DefaultChannelPipeline$HeadHandler.close(DefaultChannelPipeline.java:1018) [netty-all-4.0.10.Final.jar:na]
at io.netty.channel.DefaultChannelHandlerContext.invokeClose(DefaultChannelHandlerContext.java:560) [netty-all-4.0.10.Final.jar:na]
at io.netty.channel.DefaultChannelHandlerContext.close(DefaultChannelHandlerContext.java:545) [netty-all-4.0.10.Final.jar:na]
at io.netty.channel.DefaultChannelHandlerContext.close(DefaultChannelHandlerContext.java:423) [netty-all-4.0.10.Final.jar:na]
at cn.com.agree.afa.lsr.service.aft.codec.service.GetFile$2.exceptionCaught(GetFile.java:124) [classes/:na]
at io.netty.channel.DefaultChannelHandlerContext.invokeExceptionCaught(DefaultChannelHandlerContext.java:275) [netty-all-4.0.10.Final.jar:na]
at io.netty.channel.DefaultChannelHandlerContext.fireExceptionCaught(DefaultChannelHandlerContext.java:253) [netty-all-4.0.10.Final.jar:na]
at cn.com.agree.afa.lsr.service.aft.codec.FileReadTimeoutHandler.readTimeout(FileReadTimeoutHandler.java:147) [classes/:na]
at cn.com.agree.afa.lsr.service.aft.codec.FileReadTimeoutHandler.access$2(FileReadTimeoutHandler.java:145) [classes/:na]
at cn.com.agree.afa.lsr.service.aft.codec.FileReadTimeoutHandler$FileReadTimeoutTask.run(FileReadTimeoutHandler.java:171) [classes/:na]
at io.netty.util.concurrent.PromiseTask$RunnableAdapter.call(PromiseTask.java:38) [netty-all-4.0.10.Final.jar:na]
at io.netty.util.concurrent.ScheduledFutureTask.run(ScheduledFutureTask.java:123) [netty-all-4.0.10.Final.jar:na]
at io.netty.util.concurrent.SingleThreadEventExecutor.runAllTasks(SingleThreadEventExecutor.java:354) [netty-all-4.0.10.Final.jar:na]
at io.netty.channel.nio.NioEventLoop.run(NioEventLoop.java:348) [netty-all-4.0.10.Final.jar:na]
at io.netty.util.concurrent.SingleThreadEventExecutor$2.run(SingleThreadEventExecutor.java:101) [netty-all-4.0.10.Final.jar:na]
at java.lang.Thread.run(Thread.java:662) [na:1.6.0_43]
java.nio.channels.ClosedChannelException: null
我的猜测是这样的,ctx.close()调用一次setFailure方法,而operationComplete执行完后也会调用ctx的setFailure方法,但是这时它调用的ctx已经被关闭了。所以有了上面的空指针异常。
我的问题是:
1,上面的错误是什么原因呢?
2,有没有更好的方法来实现下载超时?
任何意见或看法都感激不尽,谢谢!!
相关推荐
netty的长连接.. 连接断开之后 自动重连demo
java作为服务端,websocket利用netty做连接,解压之后内有html前端,把项目导入eclipse,在main方法启动即可使用。
NULL 博文链接:https://gjp014.iteye.com/blog/2390925
具体信息查看我的博客:https://blog.csdn.net/qq_37437983/article/details/86585079
netty心跳连接代码
Netty4长连接、断开重连、心跳检测、Msgpack编码解码 http://blog.csdn.net/giousa/article/details/72846303#t2
netty的简介,netty是一种socket技术,实现长连接,此技术更加成熟
里面有android前端和java服务器源码,主要演示socket长连接netty框架的简单使用,想学习socket的同学可以下来看看,
Netty实现长连接通讯,连接协议为了简单json封装,如果需要协议变化可以自己封装,有问题可以联系邮箱:lmjlimj@foxmail.com
用netty实现长连接和心跳监测的示例代码
Netty通过WebSocket编程实现服务器和客户端长连接Demo
NULL 博文链接:https://mocha-c-163-com.iteye.com/blog/2266786
1、下载后导入eclipse(maven工程) 2、先运行ServerTest 3、再运行ClientTest,即可看到输出结果 4、保证可用,亲手编写,欢迎大家指正不足
netty-leanring netty长连接复用的demo
概述 在实际的生产项目中,尤其是soa架构的系统。...netty简单的长连接 pom文件 <groupId>org.springframework.boot <artifactId>spring-boot-starter-parent <version>1.5.1.RELEASE <!--
netty+proto client和server连接登录demo。 Netty是由JBOSS提供的一个java开源框架。Netty提供异步的、事件驱动的网络应用程序框架和工具,用以快速开发高性能、高可靠性的网络服务器和客户端程序。
客户端发送16进制给服务端,并行实现socket通道活动状态和断开重新连接的功能, 监听接口是否存在数据,如果存在socket客户端发送给socket服务端的实现 随着物联网的发展,随之出现了各种传感器监测数据的实时发送,...
Netty中实现多客户端连接与通信-以实现聊天室群聊功能为例示例代码
用nio实现异步连接池
Netty中使用WebSocket实现服务端与客户端的长连接通信发送消息示例代码;Netty中使用WebSocket实现服务端与客户端的长连接通信发送消息示例代码;Netty中使用WebSocket实现服务端与客户端的长连接通信发送消息示例代码