我正在使用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
,但结果不会更改。首次启动时,它会从设备接收正确的协议字符串,但如果我尝试断开重新连接,问题就会再次出现。
答案 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);
}
感谢您的帮助