Netty - 客户难读的回应

时间:2014-03-25 18:09:43

标签: java tcp netty

我正在使用Netty 4将协议字符串发送到应该使用其他协议字符串应答的设备。我做了两个类,EthClient和EthClientHandler。

EthClient:

connection = new EthClientHandler(message);
b.group(group)
        .channel(NioSocketChannel.class)
        .remoteAddress(host, port)
        .option(ChannelOption.TCP_NODELAY, true)
        .option(ChannelOption.SO_KEEPALIVE, true)
        .handler(new ChannelInitializer<SocketChannel>() {
              @Override
              public void initChannel(SocketChannel ch) throws Exception {
                  ch.pipeline().addLast(
                      new DelimiterBasedFrameDecoder(2048, true, Unpooled.copiedBuffer("\u0004".getBytes())),
                      new StringEncoder(),
                      new StringDecoder(),
                      new ReadTimeoutHandler(READ_TIMEOUT, TimeUnit.SECONDS),
                      connection
                   );
              }
        });
f = b.connect();
f.channel().closeFuture();
...

EthClientHandler:

public class EthClientHandler extends SimpleChannelInboundHandler<String> {
 private String message;

 public EthClientHandler(message) {
       this.message = message;
 }

 @Override
 public void channelActive(ChannelHandlerContext ctx) {
     ctx.writeAndFlush(message);
 }

 @Override
 public void channelRead0(ChannelHandlerContext ctx, String msg) throws Exception {
      gestString(msg);
      ctx.writeAndFlush(message);
 }
}

当开始连接时,它发送协议字符串但设备不回答我。 使用Wireshark了解设备是否回答了我发现此对话的内容:

 445    2.835161000 192.168.1.135   192.168.1.252   TCP 54  49570 > exlm-agent [FIN, ACK] Seq=1 Ack=1 Win=65088 Len=0
 454    2.871899000 192.168.1.252   192.168.1.135   TCP 60  exlm-agent > 49570 [FIN, ACK] Seq=1 Ack=2 Win=256 Len=0
 455    2.871947000 192.168.1.135   192.168.1.252   TCP 54  49570 > exlm-agent [ACK] Seq=2 Ack=2 Win=65088 Len=0
 617    3.835746000 192.168.1.135   192.168.1.252   TCP 66  49575 > exlm-agent [SYN] Seq=0 Win=8192 Len=0 MSS=1460 WS=4 SACK_PERM=1
 622    3.866775000 192.168.1.252   192.168.1.135   TCP 60  exlm-agent > 49575 [SYN, ACK] Seq=0 Ack=1 Win=256 Len=0 MSS=576
 623    3.866839000 192.168.1.135   192.168.1.252   TCP 54  49575 > exlm-agent [ACK] Seq=1 Ack=1 Win=65088 Len=0
 624    3.867209000 192.168.1.135   192.168.1.252   IPA 57  unknown 0x04 [Malformed Packet]
 641    3.937626000 192.168.1.252   192.168.1.135   TCP 60  exlm-agent > 49575 [ACK] Seq=1 Ack=4 Win=256 Len=0

所以在最后一次ACK之后我没有收到任何其他信息并且连接进入Read Timeout。 如果我在通道sturtup的ctx.writeAndFlush(message)上的代码中放置一个断点,并在一秒钟之后恢复程序设备发送给我协议字符串:

2036    13.113369000    192.168.1.135   192.168.1.252   TCP 66  51135 > exlm-agent [SYN] Seq=0 Win=8192 Len=0 MSS=1460 WS=4 SACK_PERM=1
2037    13.144752000    192.168.1.252   192.168.1.135   TCP 60  exlm-agent > 51135 [SYN, ACK] Seq=0 Ack=1 Win=256 Len=0 MSS=576
2038    13.144833000    192.168.1.135   192.168.1.252   TCP 54  51135 > exlm-agent [ACK] Seq=1 Ack=1 Win=65088 Len=0
2069    13.319494000    192.168.1.135   192.168.1.252   IPA 57  unknown 0x04 [Malformed Packet]
2073    13.366926000    192.168.1.252   192.168.1.135   TCP 60  exlm-agent > 51135 [ACK] Seq=1 Ack=4 Win=256 Len=0
2092    13.458136000    192.168.1.252   192.168.1.135   IPA 72  unknown 0x30 [Malformed Packet]
2093    13.460564000    192.168.1.135   192.168.1.252   IPA 57  unknown 0x04 [Malformed Packet]
2102    13.514205000    192.168.1.252   192.168.1.135   TCP 60  exlm-agent > 51135 [ACK] Seq=19 Ack=7 Win=256 Len=0
2123    13.621507000    192.168.1.252   192.168.1.135   IPA 72  unknown 0x30 [Malformed Packet]

所以我真的不明白为什么会有这样的结果。有人知道如何解决它?这可能是Netty问题还是设备问题?

修改: 在引导程序处理程序中添加了DelimiterBasedFramdeDecoder,但结果不会更改。首次启动时,它会从设备接收正确的协议字符串,但如果我尝试断开重新连接,问题就会再次出现。

2 个答案:

答案 0 :(得分:3)

StringDecoder需要一个成帧解码器。放置LineBasedFrameDecoder以正确处理文本行。

StringEncoder不会为您追加"\r\n"。如果你没有,请做。

这两项改变可能会使它发挥作用。

答案 1 :(得分:0)

已解决在ctx.writeAndFlush(message)的EthClientHandler类中在channelActive之前添加暂停。

@Override
public void channelActive(final ChannelHandlerContext ctx) {

    ctx.channel().eventLoop().schedule(new Runnable() {
        @Override
        public void run() {
            ctx.writeAndFlush(message);
        }
    }, 1, TimeUnit.SECONDS);
}

感谢您的帮助