我用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,有没有更好的方法来实现下载超时?
任何意见或看法都感激不尽,谢谢!!
相关推荐
8. **异常处理和连接管理**:Netty提供了优雅的异常处理机制,并能自动处理连接的关闭和重连。 9. **实例代码**:通常会包含如何配置和启动一个支持长连接的Netty服务器,以及客户端如何连接和发送数据的示例代码。...
Netty 是一个高性能、异步事件驱动的网络应用程序框架,用于快速开发可维护的高性能协议服务器和客户端。...同时,通过自定义 ChannelHandler,我们可以灵活地处理异常情况,比如在连接断开后执行重连操作。
总之,Android与Netty服务器连接需要配置Bootstrap,选择合适的通道类型,定义自定义处理器,并处理连接、读写和异常情况。在实际应用中,还需要考虑Android平台的特性和限制,以确保服务的稳定性和效率。
WebSocket是一种在客户端和服务器之间建立持久连接的协议,它允许双方进行全双工通信,即数据可以在任意方向流动,而无需反复发起请求。在Web开发中,WebSocket为实时交互提供了强大的支持,比如在线聊天、股票实时...
在TCP/IP通信中,长连接是指在完成一次数据传输后,连接不被立即关闭,而是保持一段时间,以便再次传输数据,从而减少建立和关闭连接的开销。在Netty4中,通过Channel和ChannelHandlerContext实现长连接,它们是...
在 Netty 中,我们可以通过在 `ChannelHandlerContext` 上调用 `channelInactive()` 来实现这一目标,这会在连接断开时被触发,允许我们执行清理工作。 5. **源码分析** 分析 Netty 源码可以帮助我们理解端口关闭...
长连接是指在一次连接建立后,客户端和服务器端可以多次发送和接收数据,而不需要反复建立和关闭连接,从而提高了通信效率。 Netty是一个高性能、异步事件驱动的网络应用程序框架,用于快速开发可维护的高性能协议...
标题中的“基于netty实现的支持长连接的rpc”是指利用Netty框架构建一个远程过程调用(RPC)系统,该系统能够维持长时间的连接状态,提高通信效率。Netty是一个高性能、异步事件驱动的网络应用程序框架,适用于开发...
Netty的长连接特性指的是在网络通信中,一旦连接建立,就会保持这个连接状态,直到连接的一方主动关闭或者因为网络问题断开。相比短连接,长连接在高并发、低延迟的场景下优势明显,因为它避免了频繁创建和销毁连接...
netty心跳连接代码
同时,记得在`channelInactive`或`exceptionCaught`方法中处理连接断开或异常情况。 标签"聊天"表明这是一个面向聊天应用的示例。在聊天应用中,用户可能会发送各种类型的消息,包括文本、图片等。你可能需要扩展...
在分布式锁的实现中,Netty的长连接特性使得客户端与服务端之间的通信更为高效,减少了每次请求建立和断开连接的开销。通过自定义协议设计,可以将锁的获取、释放等操作以特定的格式封装在数据包中,便于在网络中...
如果一段时间内没有收到心跳回应,可以认为连接已断开,从而进行重新连接。 Android Studio的集成使得Netty的使用更为方便。在Android环境中,由于安全和权限限制,我们通常需要在后台服务中运行Netty服务器,而在...
如果服务器未在规定时间内收到回应,可以认为连接已断开,然后进行相应的处理,如关闭连接。 3. **客户端连接控制**: Netty 提供了灵活的连接管理功能。例如,我们可以在服务端设置一个MaxConnectionsHandler,...
同时,为了保证网络通信的健壮性,还需要处理各种异常情况,如连接断开、数据丢失等。 在实现过程中,可能会遇到的问题包括网络延迟、数据同步问题、线程安全等。因此,对并发编程和网络编程有深入理解是非常重要的...
4. **实现重连逻辑**: 当检测到连接断开或心跳超时时,使用 `ChannelFutureListener` 注册到 `Channel.closeFuture()`,在 Channel 关闭后执行重连操作。 5. **配置重试策略**: 可以设置重试次数、重试间隔等参数,...
4. **异常处理**:定义异常处理器,捕获并处理可能出现的网络异常,如连接断开、超时等。 5. **数据处理**:根据业务需求,解析接收到的数据并进行相应的业务逻辑处理,如存储数据、触发报警、执行远程控制等。 6....
- Netty 提供了 ChannelIdleHandler,可以在连接空闲一定时间后触发事件,以便执行心跳或关闭连接操作。 6. **安全性与性能优化** - Netty 支持 SSL/TLS 加密,可以为 WebSocket 连接提供安全保护。 - 通过配置...
Boss线程负责接收新的连接请求,而Worker线程则处理这些连接后的读写操作,这种模型能够有效提高系统的并发能力。Netty的NIO(非阻塞I/O)模型使得它在处理高并发场景下表现出色。 Netty的Channel和Pipeline是两个...
8. **异常处理**:Netty提供了一套完整的异常处理机制,使得在发生错误时能够优雅地恢复或关闭连接。 9. **丰富的API**:Netty的API设计简洁且强大,易于理解和使用,降低了开发网络应用的门槛。 10. **社区活跃**...