1、先说问题
背景:服务是运行在Linux上的安全网关提供的,TCP协议发送 通过二进制编码的xml字符串 报文,报文头的第一个字段是int类型的表示字节序标记,第二个字段是int类型的表示整个报文长度。
现象:数据量较小时完全可以正常收发报文,当服务端发送的报文数据量较大时(本例是将近600k)概率性出现接收数据直接调用readComplete()方法而没有走channelRead()
跟踪:跟踪代码发现出问题时context 的 read() 方法执行中读取到一百多k(有时两百多也可能三百多,总之是还没读取到全部数据)时某次读到的数据本应该是1024字节(填满默认分配的ByteBuf)却只读到了576字节;
netty框架代码中判断如果当前读到的字节数小于ByteBuf的size则认为是读取完成,因此调用了readComplete()方法,出错。。。
解决方案:在ClientHandler类添加一个标记flag,用于是否正常读取数据判断。channelRead()方法正常调用则将其置为true;readComplete方法中添加一个判断只有当flag为true时关闭context否则继续调用ctx.read()。
2、再上核心代码
Client:
1 ClientHandler clientHandler = new ClientHandler(this); 2 bootstrap.group(eventLoop) 3 .channel(NioSocketChannel.class) 4 .option(ChannelOption.TCP_NODELAY, true) 5 .option(ChannelOption.CONNECT_TIMEOUT_MILLIS, 3000) 6 .option(ChannelOption.MAX_MESSAGES_PER_READ, Integer.MAX_VALUE) 7 .handler(new ClientChannelInitializer(clientHandler)); 8 9 ChannelFuture f = bootstrap.connect(host, port).sync(); 10 11 f.channel().closeFuture().sync();
1 private class ClientChannelInitializer extends ChannelInitializer<SocketChannel> { 2 private ClientHandler clientHandler; 3 4 public ClientChannelInitializer(ClientHandler clientHandler) { 5 this.clientHandler = clientHandler; 6 } 7 8 @Override 9 protected