0 0

Netty关闭连接后引发的空指针异常25

我用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,有没有更好的方法来实现下载超时?

 

任何意见或看法都感激不尽,谢谢!!

2014年9月28日 16:49

1个答案 按时间排序 按投票排序

0 0

你不是已经分析出来了么...类似socket已经关闭了,然后再close,就会引发异常。

Channel channel = future.getChannel();
然后判断一下
channel.isOpen() && channel.isConnected() 如果可以再ctx.close()

不清楚你的ctx是什么,是ChannelHandlerContext么?无所谓了,如果之前的人工异常触发后,channel已经close了,这里就应该可以判断出来,从而你不用再次ctx.close了。


题外话,服务器向客户端写数据的时候,有没有类似这样的判断
channel != null && channel.isOpen() && channel.isConnected() && channel.isWritable()

按理说这次通讯的链路都断了,怎么会跑到 operationComplete 方法里...

2014年9月29日 18:12

相关推荐

    netty 实现长连接

    8. **异常处理和连接管理**:Netty提供了优雅的异常处理机制,并能自动处理连接的关闭和重连。 9. **实例代码**:通常会包含如何配置和启动一个支持长连接的Netty服务器,以及客户端如何连接和发送数据的示例代码。...

    netty5长连接.自动重连

    Netty 是一个高性能、异步事件驱动的网络应用程序框架,用于快速开发可维护的高性能协议服务器和客户端。...同时,通过自定义 ChannelHandler,我们可以灵活地处理异常情况,比如在连接断开后执行重连操作。

    Android与Netty服务器连接

    总之,Android与Netty服务器连接需要配置Bootstrap,选择合适的通道类型,定义自定义处理器,并处理连接、读写和异常情况。在实际应用中,还需要考虑Android平台的特性和限制,以确保服务的稳定性和效率。

    WebSocket利用netty连接入门项目

    WebSocket是一种在客户端和服务器之间建立持久连接的协议,它允许双方进行全双工通信,即数据可以在任意方向流动,而无需反复发起请求。在Web开发中,WebSocket为实时交互提供了强大的支持,比如在线聊天、股票实时...

    Netty4长连接(服务端+客户端)

    在TCP/IP通信中,长连接是指在完成一次数据传输后,连接不被立即关闭,而是保持一段时间,以便再次传输数据,从而减少建立和关闭连接的开销。在Netty4中,通过Channel和ChannelHandlerContext实现长连接,它们是...

    netty 通过端口调用关闭

    在 Netty 中,我们可以通过在 `ChannelHandlerContext` 上调用 `channelInactive()` 来实现这一目标,这会在连接断开时被触发,允许我们执行清理工作。 5. **源码分析** 分析 Netty 源码可以帮助我们理解端口关闭...

    socket长连接,netty服务器与android源码

    长连接是指在一次连接建立后,客户端和服务器端可以多次发送和接收数据,而不需要反复建立和关闭连接,从而提高了通信效率。 Netty是一个高性能、异步事件驱动的网络应用程序框架,用于快速开发可维护的高性能协议...

    基于netty实现的支持长连接的rpc

    标题中的“基于netty实现的支持长连接的rpc”是指利用Netty框架构建一个远程过程调用(RPC)系统,该系统能够维持长时间的连接状态,提高通信效率。Netty是一个高性能、异步事件驱动的网络应用程序框架,适用于开发...

    Netty简介.pdf(长连接)

    Netty的长连接特性指的是在网络通信中,一旦连接建立,就会保持这个连接状态,直到连接的一方主动关闭或者因为网络问题断开。相比短连接,长连接在高并发、低延迟的场景下优势明显,因为它避免了频繁创建和销毁连接...

    netty心跳连接代码

    netty心跳连接代码

    Netty实现长连接通讯-连接协议为了简单json封装

    同时,记得在`channelInactive`或`exceptionCaught`方法中处理连接断开或异常情况。 标签"聊天"表明这是一个面向聊天应用的示例。在聊天应用中,用户可能会发送各种类型的消息,包括文本、图片等。你可能需要扩展...

    分布式锁,基于Netty长连接实现,自定义协议,高性能锁

    在分布式锁的实现中,Netty的长连接特性使得客户端与服务端之间的通信更为高效,减少了每次请求建立和断开连接的开销。通过自定义协议设计,可以将锁的获取、释放等操作以特定的格式封装在数据包中,便于在网络中...

    Android使用Netty网络框架实践(客户端、服务端)

    如果一段时间内没有收到心跳回应,可以认为连接已断开,从而进行重新连接。 Android Studio的集成使得Netty的使用更为方便。在Android环境中,由于安全和权限限制,我们通常需要在后台服务中运行Netty服务器,而在...

    NettySocket同步数据获取实现

    如果服务器未在规定时间内收到回应,可以认为连接已断开,然后进行相应的处理,如关闭连接。 3. **客户端连接控制**: Netty 提供了灵活的连接管理功能。例如,我们可以在服务端设置一个MaxConnectionsHandler,...

    Netty实现Java服务端和C#客户端联通

    同时,为了保证网络通信的健壮性,还需要处理各种异常情况,如连接断开、数据丢失等。 在实现过程中,可能会遇到的问题包括网络延迟、数据同步问题、线程安全等。因此,对并发编程和网络编程有深入理解是非常重要的...

    netty断线重连机制及心跳机制.rar

    4. **实现重连逻辑**: 当检测到连接断开或心跳超时时,使用 `ChannelFutureListener` 注册到 `Channel.closeFuture()`,在 Channel 关闭后执行重连操作。 5. **配置重试策略**: 可以设置重试次数、重试间隔等参数,...

    netty+4G DTU

    4. **异常处理**:定义异常处理器,捕获并处理可能出现的网络异常,如连接断开、超时等。 5. **数据处理**:根据业务需求,解析接收到的数据并进行相应的业务逻辑处理,如存储数据、触发报警、执行远程控制等。 6....

    整合netty实时通讯

    - Netty 提供了 ChannelIdleHandler,可以在连接空闲一定时间后触发事件,以便执行心跳或关闭连接操作。 6. **安全性与性能优化** - Netty 支持 SSL/TLS 加密,可以为 WebSocket 连接提供安全保护。 - 通过配置...

    深入浅出Netty_netty_

    Boss线程负责接收新的连接请求,而Worker线程则处理这些连接后的读写操作,这种模型能够有效提高系统的并发能力。Netty的NIO(非阻塞I/O)模型使得它在处理高并发场景下表现出色。 Netty的Channel和Pipeline是两个...

    Netty实战 电子版.pdf_java_netty_服务器_

    8. **异常处理**:Netty提供了一套完整的异常处理机制,使得在发生错误时能够优雅地恢复或关闭连接。 9. **丰富的API**:Netty的API设计简洁且强大,易于理解和使用,降低了开发网络应用的门槛。 10. **社区活跃**...

Global site tag (gtag.js) - Google Analytics