在连接超时时从Netty发送非禁止的408响应

时间:2019-06-23 08:07:54

标签: java netty

根据the specs,如果HTTP服务器在特定时间内未收到请求,则应发送408。这有点不直观,因为这意味着您可以在不接收请求的情况下发送响应。一个目的是杀死客户端尚未关闭的长期保持活动的HTTP 1.1连接。

为此,我在其中添加了一个IdleStateEvent事件:

DefaultFullHttpResponse resp = new DefaultFullHttpResponse(HTTP_1_1, 
                                          HttpResponseStatus.REQUEST_TIMEOUT);
resp.headers().set(HttpHeaderNames.CONNECTION, HttpHeaderValues.CLOSE);
ctx.writeAndFlush(resp)
    .addListener(future -> {
        System.out.println("Finished " + future.cause());
    })
    .addListener(ChannelFutureListener.CLOSE);

输出:

Finished io.netty.handler.codec.EncoderException: java.lang.IllegalStateException: cannot send more responses than requests

在Netty中有没有办法做到这一点?还是建议的方法来关闭空闲的HTTP 1.1连接?

1 个答案:

答案 0 :(得分:0)

根据Netty javadoc,您可以使用IdleStateHandler类关闭空闲连接。显然,当连接在一段时间内没有读,写或没有写时,此处理程序将触发IdleStateEvent。然后,可以使用此事件触发关闭连接...或执行其他操作。

以下示例是从javadoc复制的:

 // An example that sends a ping message when there is no outbound traffic
 // for 30 seconds.  The connection is closed when there is no inbound traffic
 // for 60 seconds.

 public class MyChannelInitializer extends ChannelInitializer<Channel> {
      @Override
     public void initChannel(Channel channel) {
         channel.pipeline().addLast("idleStateHandler", new IdleStateHandler(60, 30, 0));
         channel.pipeline().addLast("myHandler", new MyHandler());
     }
 }

 // Handler should handle the IdleStateEvent triggered by IdleStateHandler.
 public class MyHandler extends ChannelDuplexHandler {
      @Override
     public void userEventTriggered(ChannelHandlerContext ctx, Object evt) throws Exception {
         if (evt instanceof IdleStateEvent) {
             IdleStateEvent e = (IdleStateEvent) evt;
             if (e.state() == IdleState.READER_IDLE) {
                 ctx.close();
             } else if (e.state() == IdleState.WRITER_IDLE) {
                 ctx.writeAndFlush(new PingMessage());
             }
         }
     }
 }

 ServerBootstrap bootstrap = ...;
 ...
 bootstrap.childHandler(new MyChannelInitializer());
 ...

注意:根据this Q&AIdleStateHandler应该是管道中的第一个处理程序。