Netty没有发送某些字符序列

时间:2014-09-30 10:03:58

标签: java netty

我开始熟悉Netty,因为我计划在未来的项目中使用它。

但我偶然发现了一些奇怪的行为。

由于我将为项目使用文本协议,因此我开始使用StringDecoder,StringEncoder和DelimiterBasedFrameDecoder的标准“text”管道。但现在我把它减少到以下几点:

EventLoopGroup workerGroup = new NioEventLoopGroup();
try {
    Bootstrap b = new Bootstrap(); 
    b.group(workerGroup); 
    b.channel(NioSocketChannel.class);
    b.handler(new ChannelInitializer<SocketChannel>() {
    @Override
    public void initChannel(SocketChannel ch) throws Exception {
        ch.pipeline().addLast(new TestClientHandler());
        }
    });

    ChannelFuture f = b.connect("some.working.web.server", 80).sync();
    f.channel().closeFuture().sync();
    } finally {
        workerGroup.shutdownGracefully();
}

我的TestClient是:

public static class TestClientHandler extends
            SimpleChannelInboundHandler<ByteBuf> {

@Override
public void channelActive(ChannelHandlerContext ctx) throws Exception {
    System.out.println("channel active");
    ctx.writeAndFlush(Unpooled.copiedBuffer(
      "GET /index.html HTTP/1.0\r\n", CharsetUtil.US_ASCII));
    System.out.println("after write");
}

@Override
public void channelRead0(ChannelHandlerContext ctx, ByteBuf msg) {
    System.out.println("got" + msg);
}

@Override
public void exceptionCaught(ChannelHandlerContext ctx, Throwable cause) {
    cause.printStackTrace();
    ctx.close();
}
}

我用Wireshark查看了流量,当执行此操作时,仅执行TCP握手并且不发送任何内容。一段时间后程序退出(当HTTP服务器关闭连接时)。

最奇怪的是,如果我换行:

ctx.writeAndFlush(Unpooled.copiedBuffer(
          "GET /index.html HTTP/1.0\r\n", CharsetUtil.US_ASCII));

ctx.writeAndFlush(Unpooled.copiedBuffer(
          "GET /index.html HTTPA1.0\r\n", CharsetUtil.US_ASCII));

然后“请求”被发送到服务器,当然拒绝它并回复错误。

我更多地使用了“请求字符串”,似乎Netty由于某种原因不喜欢以下内容:

ctx.writeAndFlush(Unpooled.copiedBuffer(
                    " HTTP/1.0\n", CharsetUtil.US_ASCII));

此字符串未发送。但是删除前导空格或更改随机字符会将字符串发送到服务器。

为了让事情更奇怪,如果我用SMTP服务器测试它,“请求”会毫无问题地发送到服务器。唯一的区别是SMTP服务器在我的字符串发送到服务器之前发送HELO消息...

在Java 1.7.0_21和1.8.0_20上,行为也与Netty 4.0.23和4.1.0.Beta3相同。 如果我改为OioEventLoopGroup和OioSocketChannel

,也会保持不变

还要改变channelActive方法:

@Override
public void channelActive(ChannelHandlerContext ctx) throws Exception {
    System.out.println("channel active");
    ByteBuf bb = Unpooled.buffer();
    bb.writeBytes("GET index.htm HTTP/1.0\r\n".getBytes());
    System.out.println(ByteBufUtil.hexDump(bb));
    ctx.writeAndFlush(bb);
    System.out.println("after write");
}

显示我的“请求”变为正确的字节序列:

47455420696e6465782e68746d20485454502f312e300d0a
G E T   i n d e x . h t m   H T T P / 1 . 0 \r\n

如果有人对这种诡计有解释,我将不胜感激......

1 个答案:

答案 0 :(得分:0)

此问题原来是由防病毒软件引起的。 显然我正在使用的软件使用hacky解析器进行HTTP监控,它吃了我的“请求”,实际上是无效的......最后缺少额外的\ r \ n。

关闭防病毒功能解决了这个问题。并将请求更正为:

  

GET /index.html HTTP / 1.0 \ r \ n \ r \ n

保持杀毒软件的快乐。

但为什么决定吃饭

  

GET /index.html HTTP / 1.0 \ r \ n

而不是

  

GET /index.html HTTPA / 1.0 \ r \ n

超出我的范围......