如果我在写入响应后立即关闭通道会发生什么?是否仍然提供响应?
这个http 上传示例似乎是这样说的,但我不确定它是否只是一个错误。
writeResponse(ctx.channel());
ctx.channel().close();
Run Code Online (Sandbox Code Playgroud)
如果您.close()
在写入后立即使用关闭通道,那么您将创建一个竞争条件,其中要么写入所有数据,要么写入一半数据,甚至不写入,具体取决于消息的长度。
发生这种情况是因为所有写入的消息最终都会进入一个队列,并且取决于当前线程是否为 Netty 线程,它要么处理数据目录,要么直接返回。
由于在大多数情况下您只想在所有写入完成后关闭通道,因此在编写响应时应使用以下代码:
ctx.writeAndFlush(protocolSpecificPacket)
.addListener(ChannelFutureListener.CLOSE);
Run Code Online (Sandbox Code Playgroud)
虽然这总是有效,但您并不总是可以访问最后一次写入,在这些情况下,您也可以发送一个空的ByteBuf
,然后将侦听器添加到其中:
ctx.writeAndFlush(Unpooled.EMPTY_BUFFER)
.addListener(ChannelFutureListener.CLOSE);
Run Code Online (Sandbox Code Playgroud)
不,这不是一个错误,但不是关闭通道的最佳方法,我假设你 writeResponse 执行如下:
ctx.channel().write(msg)
Run Code Online (Sandbox Code Playgroud)
它是异步发送的,实际上消息将提供给 writeBufferQueue,并且写入 IO 线程将被唤醒以进行实际写入。
检查ChannelFuture
ctx.channel().write(msg) 返回的内容,您可以等待该对象。
我认为关闭 netty 通道的最佳方法是:
ctx.channel().write(a emptybuffer).addFutureListener(Channels.CloseFuture);
Run Code Online (Sandbox Code Playgroud)
由于您使用的是netty 4.0,您可能需要搜索与上面类似的内容。