Netty ReadComplete()调用了两次

Netty ReadComplete()调用了两次,netty,Netty,注意:此问题以前曾发布过,但现在使用ChannelOption.MAX_MESSAGES_PER_READ解决方案不起作用。此外,该选项已弃用 注:作为提醒。。我和内蒂是新手 使用Netty4.1.51,当我用“curl-v”刺激下面的代码时http://localhost:8080/'时,我的程序的控制台输出显示: Server listening on 8080 Read GET / HTTP/1.1 Host: localhost:8080 User-Agent: curl/7.71.1

注意:此问题以前曾发布过,但现在使用ChannelOption.MAX_MESSAGES_PER_READ解决方案不起作用。此外,该选项已弃用

注:作为提醒。。我和内蒂是新手

使用Netty4.1.51,当我用“curl-v”刺激下面的代码时http://localhost:8080/'时,我的程序的控制台输出显示:

Server listening on 8080
Read
GET / HTTP/1.1
Host: localhost:8080
User-Agent: curl/7.71.1
Accept: */*

ReadComplete
Write Hello
flush
ReadComplete
Write Hello
flush
处理程序read()方法被调用一次,readComplete()方法被调用两次,然而,curl似乎对这种交换感到高兴

curl -v http://localhost:8080/
*   Trying ::1:8080...
* Connected to localhost (::1) port 8080 (#0)
> GET / HTTP/1.1
> Host: localhost:8080
> User-Agent: curl/7.71.1
> Accept: */*
>
* Mark bundle as not supporting multiuse
< HTTP/1.1 200 ok
< Content-Type: text/plain
< Content-Length: 5
<
Hello* Connection #0 to host localhost left intact
curl-vhttp://localhost:8080/
*正在尝试::1:8080。。。
*已连接到本地主机(::1)端口8080(#0)
>GET/HTTP/1.1
>主机:本地主机:8080
>用户代理:curl/7.71.1
>接受:*/*
>
*将捆绑包标记为不支持多用途
我似乎不明白发生了什么事。。最近有人遇到过这个问题吗

readComplete()不应该在一次或多次读取后发生一次吗

感谢所有有空闲时间看这个的人

-jmr


private static void bootstrap1(){
int端口=8080;
EventLoopGroup=new NioEventLoopGroup();
ServerBootstrap bootstrap=newserverbootstrap();
独自创立
.集团(集团)
.channel(NioServerSocketChannel.class)
.childHandler(新的通道初始值设定项()
{
@覆盖受保护的通道(SocketChannel ch)
抛出异常
{
ChannelPipeline=通道管道();
addLast(“out”,newouthandler());
addLast(“in”,new InHandler());
}
});
ChannelFuture=bootstrap.bind(新的InetSocketAddress(端口));
future.addListener((ChannelFutureListener)(ChannelFuture1)->
{
if(future1.issucess()){
pr(“服务器侦听”+端口);
}否则{
未来1.原因().printStackTrace();
}
});        
}
Handler中的私有静态类扩展ChannelInboundHandlerAdapter{
@凌驾
public void channelRead(ChannelHandlerContext ctx,Object msg)引发异常{
公共关系(“阅读”);
if(msg instanceof ByteBuf){
ByteBuf buf=(ByteBuf)味精;
pr(“+buf.readCharSequence(buf.readableBytes(),Charset.defaultCharset());
}
ctx.fireChannelRead(msg);
}
@覆盖公共无效channelReadComplete(ChannelHandlerContext ctx)
抛出异常
{
pr(“重新完成”);
ByteBuf buf=unmooled.buffer();
buf.writeCharSequence(“Hello”,Charset.defaultCharset());
ctx.writeAndFlush(buf);
ctx.fireChannelReadComplete();
}
}
私有静态类OutHandler扩展了ChannelOutboundHandlerAdapter{
@重写公共无效写入(ChannelHandlerContext ctx,对象消息,
渠道(承诺)
抛出异常
{
ByteBuf in=(ByteBuf)味精;
pr(“Write”+in.getCharSequence(0,in.readableBytes(),Charset.defaultCharset());
ByteBuf buf=unmooled.buffer();
buf.writeCharSequence(“HTTP/1.1 200 ok\r\n”,Charset.defaultCharset());
buf.writeCharSequence(“内容类型:text/plain\r\n”,Charset.defaultCharset());
buf.writeCharSequence(“内容长度:5\r\n\r\n”,Charset.defaultCharset());
buf.writeCharSequence(in.readCharSequence(5,Charset.defaultCharset()),Charset.defaultCharset());
in.release();
ctx.write(buf);
}
@覆盖公共无效刷新(ChannelHandlerContext ctx)
抛出异常
{
公共关系(“同花顺”);
ctx.flush();
}
}

除了调用两次
channelReadComplete
之外,您还编写了两次HTTP响应,这由重复的“Write Hello”日志消息指示

channelReadComplete
被调用两次,因为自动读取已打开(默认情况下会发生)。要关闭该选项并触发初始只读,您可以修改
通道初始值设定项
,如下所示:

.childHandler(new ChannelInitializer<SocketChannel>()
{
    @Override protected void initChannel(SocketChannel ch)
        throws Exception
    { 
        ChannelPipeline pipeline = ch.pipeline();
        pipeline.addLast("out", new OutHandler());
        pipeline.addLast("in", new InHandler());
        ch.config().setAutoRead(false);
        ch.read();
    }
});
.childHandler(新的通道初始值设定项()
{
@覆盖受保护的通道(SocketChannel ch)
抛出异常
{ 
ChannelPipeline=通道管道();
addLast(“out”,newouthandler());
addLast(“in”,new InHandler());
ch.config().setAutoRead(false);
ch.read();
}
});
话虽如此,
channelReadComplete
并不是创建和发送响应的正确位置。在您的情况下,这样做会导致双重发送响应。卷曲也许可以,但这不是你想要的。一旦收集到完整的请求,
channelRead
方法是发送响应的更好地方

有关参考echo服务器,请查看以下内容:

我强烈推荐NIA的书,让你在所有的事情上都能找到正确的方向

.childHandler(new ChannelInitializer<SocketChannel>()
{
    @Override protected void initChannel(SocketChannel ch)
        throws Exception
    { 
        ChannelPipeline pipeline = ch.pipeline();
        pipeline.addLast("out", new OutHandler());
        pipeline.addLast("in", new InHandler());
        ch.config().setAutoRead(false);
        ch.read();
    }
});